声明变量
var
es6之前的开发声明变量用的关键字,因为问题比较多,所以差不多可以淘汰了,之后声明变量我们最好不用var,尽量用const和let。
let
let声明的值可以更改 但是有作用域,const也有作用域,这就涉及到全局变量和局部变量
const
const语义化更好,const 声明的值不能更改,而且const声明变量的时候需要里面进行初始化。
但是对于引用数据类型来说,我们可以更改,因为这字面存的不是值,而是地址。
DOM
什么是DOM
DOM对象
浏览器根据html标签生成的js对象
获取DOM对象 匹配到的第一个元素 可以直接操作修改
document.querySelector('css选择器')
选择匹配的多个元素 返回的是伪数组集合 不可以直接操作修改 需要遍历得到每一个元素
document.querySelectorAll('css选择器')
操作元素内容
元素.innerText属性 只能识别文本 不能解析标签
元素.innerHTML属性 能识别文本 ,能解析标签
操作元素的属性
对象.属性=值
操作元素的样式属性
对象.style.样式属性 = '值'
操作类
元素.className='类名'
元素.className.add('类名') 追加类
元素.className.remove('类名') 删除类
元素.className.toggle('类名') 切换类
综合案例
每次刷新页面的时候让这十张背景图片随机播放
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
html,
body {
width: 100%;
height: 100%;
}
body {
background: url(./images/desktop_1.jpg) no-repeat center center/cover;
}
</style>
</head>
<body>
<script>
//获取body不能使用 document.querySelector 而是用document.body
//html元素使用document.element
//生成随机的函数
function getRandom(N, M) {
return Math.floor(Math.random() * (M - N + 1)) + N;
}
//给随机数函数传参
const random = getRandom(1, 10);
//利用背景图的数字来进行模板字符串拼接达到随机更换图片
document.body.style.backgroundImage = `url(./images/desktop_${random}.jpg)`;
</script>
</body>
</html>
事件
事件是编程语言中的术语,它是用来描述程序的行为或状态的,一旦行为或状态发生改变,便立即调用一个函数。
比如:鼠标点击一个按钮
事件监听
监听这个事件,当事件触发时便立即调用一个函数。
addEventListener
是 DOM 对象专门用来添加事件监听的方法,它的两个参数分别为【事件类型】和【事件回调】。
<button id="btn">点击改变文字颜色</button>
<script>
// 1. 获取 button 对应的 DOM 对象
const btn = document.querySelector('#btn')
// 2. 添加事件监听
btn.addEventListener('click', function () {
console.log('等待事件被触发...')
// 改变 p 标签的文字颜色
let text = document.getElementById('text')
text.style.color = 'red'
})
// 3. 只要用户点击了按钮,事件便触发了!!!
</script>
事件监听的三个步骤:
1.获取DOM元素
2.通过 addEventListener
方法为 DOM 节点添加事件监听
3.等待事件触发
4.事件触发,相对应的回调函数会被执行
事件类型
鼠标事件:click(点击)dblclick(双击)moerenter,mouerover(移入)mouerleave,mouerout(移出)
键盘事件:keydown(键盘按下触发)keyup(键盘抬起触发)
文本框输入事件:input
表单事件:form
焦点事件:focus(获得焦点触发)blur(失去焦点触发)
等事件
环境对象
1. this本质上是一个变量,数据类型为对象
2. 函数的调用方式不同this变量的值也不同
3. “谁调用this就是谁”是判断this的大概方向,是一个粗略规则
回调函数
当一个函数作为参数传递给另一个函数,那么这个作为参数传递的函数就是回调函数
1. 回调函数本质上还是函数,只不过把它当成参数使用
2. 使用匿名函数作为回调函数比较常见
事件流
事件被触发时会经历两个阶段:捕获阶段和冒泡阶段
简单一点说,从父向子传递的过程称为捕获阶段。从子向父传递的过程称为冒泡阶段
事件对象中的stopPropagation方法,专门用来阻止事件冒泡
鼠标经过事件:
mouseover 和 mouseout 会有冒泡效果
mouseenter 和 mouseleave 没有冒泡效果 (推荐)
事件委托
优点:减少注册次数,可以提高程序性能
原理:事件委托是利用事件冒泡的特点。
给父元素注册事件,当我们触发子元素的时候,会冒泡到父元素身上,从而触发父元素的事件。
实现:事件对象.target. tagName 可以获得真正触发事件的元素
<body>
<ul>
<li>第1个孩子</li>
<li>第2个孩子</li>
<li>第3个孩子</li>
<li>第4个孩子</li>
<li>第5个孩子</li>
<p>我不需要变色</p>
</ul>
<script>
// 点击每个小li 当前li 文字变为红色
// 按照事件委托的方式 委托给父级,事件写到父级身上
// 1. 获得父元素
const ul = document.querySelector('ul')
ul.addEventListener('click', function (e) {
// alert(11)
// this.style.color = 'red'
// console.dir(e.target) // 就是我们点击的那个对象
// e.target.style.color = 'red'
// 我的需求,我们只要点击li才会有效果
if (e.target.tagName === 'LI') {
e.target.style.color = 'red'
}
})
</script>
</body>
页面加载事件load
监听页面所有资源加载完毕
window.addEventListener('load', function() {
// xxxxx
})
元素滚动事件scroll
滚动条在滚动的时候持续触发的事件
window.addEventListener('scroll', function() {
// xxxxx
})
页面尺寸事件resize
在窗口尺寸改变的时候触发
window.addEventListener('resize', function() {
// xxxxx
})
元素尺寸与位置 offsetWidth和offsetHeight
日期对象Date
实例化
// 1. 实例化
// const date = new Date(); // 系统默认时间
const date = new Date('2022-08-20') // 指定时间
// date 变量即所谓的时间对象console.log(typeof date)
如何获取当前系统的默认时间?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div>2008-08-08 08:08</div>
<script>
// 日期格式化函数
function getMyDate() {
// 实例化日期 获取当前系统默认事件
const date = new Date();
// 获取当前年份
const y = date.getFullYear();
// 获取当前月份 月份要+1 因为获取过来的是从0开始
let m = date.getMonth() + 1;
// 补零操作 三元运算符
m = m < 10 ? "0" + m : m;
// 获取当前时间的天
let d = date.getDate();
// 补零操作 三元运算符
d = d < 10 ? "0" + d : d;
// 获取当前的小时
let h = date.getHours();
h = h < 10 ? "0" + h : h;
// 获取当前分钟
let mi = date.getMinutes();
mi = mi < 10 ? "0" + mi : mi;
// 获取当前秒
let s = date.getSeconds();
s = s < 10 ? "0" + s : s;
// 用模板字符串拼接 让日期格式化
const str = `${y}-${m}-${d} ${h}:${mi}:${s}`;
// return 返回这个格式化后的时间
return str;
}
// 获取需要放入日期的容器
const div = document.querySelector("div");
//修改容器的内容 变成当前格式化的日期内容 调用这个函数
div.innerText = getMyDate();
</script>
</body>
</html>
时间戳
时间戳是指1970年01月01日00时00分00秒起至现在的总秒数或毫秒数,它是一种特殊的计量时间的方式。
获取时间戳的方法,分别为 getTime 和 Date.now 和 +new Date()
利用时间戳写一个下课倒计时案例
背景颜色随机
html代码
<div class="countdown">
<p class="next" id="timeShow">今天是2222年2月22日</p>
<p class="title">下课倒计时</p>
<p class="clock">
<span id="hour">00</span>
<i>:</i>
<span id="minutes">25</span>
<i>:</i>
<span id="scond">20</span>
</p>
<p class="tips">17:30:00下课</p>
</div>
css代码
.countdown {
margin: 100px auto;
width: 240px;
height: 305px;
text-align: center;
line-height: 1;
color: #fff;
background-color: brown;
/* background-size: 240px; */
/* float: left; */
overflow: hidden;
}
.countdown .next {
font-size: 16px;
margin: 25px 0 14px;
}
.countdown .title {
font-size: 33px;
}
.countdown .tips {
margin-top: 80px;
font-size: 23px;
}
.countdown small {
font-size: 17px;
}
.countdown .clock {
width: 142px;
margin: 18px auto 0;
overflow: hidden;
}
.countdown .clock span,
.countdown .clock i {
display: block;
text-align: center;
line-height: 34px;
font-size: 23px;
float: left;
}
.countdown .clock span {
width: 34px;
height: 34px;
border-radius: 2px;
background-color: #303430;
}
.countdown .clock i {
width: 20px;
font-style: normal;
}
js代码
const timeShow = document.querySelector("#timeShow");
const name = new Date();
//这是指定时间 需要自己手动更改
const last = +new Date("2022-8-22 17:30:00");
timeShow.innerHTML = time();
getCountTime();
setInterval(getCountTime, 1000);
function bian() {
getRandomColor();
const countdown = document.querySelector(".countdown");
countdown.style.backgroundColor = getRandomColor();
}
setInterval(bian, 5000);
//颜色随机rgb或者16进制 默认16进制
function getRandomColor(flag = true) {
if (flag) {
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f"];
let str = "#";
for (let i = 0; i < 6; i++) {
let random = Math.floor(Math.random() * arr.length);
str = str + arr[random];
}
return str;
} else {
let r = Math.floor(Math.random() * 256);
let g = Math.floor(Math.random() * 256);
let b = Math.floor(Math.random() * 256);
return `rgb(${r},${g},${b})`;
}
}
//倒计时
function getCountTime() {
const now = +new Date();
const count = (last - now) / 1000;
let h = parseInt((count / 60 / 60) % 24);
let m = parseInt((count / 60) % 60);
let s = parseInt(count % 60);
h = h < 10 ? "0" + h : h;
m = m < 10 ? "0" + m : m;
s = s < 10 ? "0" + s : s;
document.querySelector("#hour").innerHTML = h;
document.querySelector("#minutes").innerHTML = m;
document.querySelector("#scond").innerHTML = s;
}
//获得当前时间
function time() {
let t = null;
t = setTimeout(time, 1000); //设置定时器,一秒刷新一次
function time() {
clearTimeout(t); //清除定时器
dt = new Date();
let y = dt.getFullYear();
let m = dt.getMonth() + 1;
let d = dt.getDate();
let weekday = [
"星期日",
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
];
let day = dt.getDay();
let h = dt.getHours();
let min = dt.getMinutes();
let s = dt.getSeconds();
if (h < 10) {
h = "0" + h;
}
if (min < 10) {
min = "0" + min;
}
if (s < 10) {
s = "0" + s;
}
document.querySelector(
"#timeShow"
).innerHTML = `${y}年${m}月${d}日 ${weekday[day]} ${h}:${min}:${s}
`;
t = setTimeout(time, 1000);
}
}
DOM节点
DOM节点:DOM树里面的每一个内容都称之为节点
DOM可以分为:元素节点,属性节点,文本节点。
查找节点
查找父节点: 子元素.parentNode()
查找子节点:父元素.children() 仅获得所有的元素节点,返回的是一个伪数组
父元素.childrens() 获得所有内容 包括文本节点(空格 注释等)
查找兄弟关系:
查找下一个兄弟元素:当前元素.nextElementSibling()
查找上一个兄弟元素:当前元素.previousElementSibling()
节点的操作
增加节点
1.创建节点:document.createElement('标签名')
2.追加节点:
插入到父元素的最后一个子元素:父元素.appendChild(要插入的元素)
插入到父元素中某个子元素的前面:父元素.insertBefore(要插入的元素)
<body>
<ul>
<li>武大郎</li>
</ul>
<script>
//创建节点
// const div = document.createElement("div");
//追加节点,作为最后一个子元素
// document.documentElement.appendChild(div);
const ul = document.querySelector("ul");
const li = document.createElement("li");
li.innerHTML = "我是潘金莲";
ul.appendChild(li);
//获取所有的ul下面的子元素
ul.children;
//追加节点
ul.insertBefore(li, ul.children[0]);
</script>
</body>
克隆节点:元素.cloneNode(布尔值)
true代表克隆会包含后代节点一起克隆 false代表克隆时不包含后代节点
删除节点
父元素.removeChild(要删除的元素)
本地储存
sessionStorage:关闭浏览器就会销毁数据(生命周期为关闭浏览器窗口)使用方式一样
localStorage:将数据永久存储在本地,除非手动删除,或者remove 存储的是字符串类型 以键值对的形式存储使用。
localStorage.setItem("age", "20");//存数据
localStorage.getItem("age");//取数据
localStorage.removeItem("age");//删除数据
因为本地存储的只能是字符串类型 所以当我们需要存储复杂数据类型的时候需要进行转换后存储
存:JSON.stringify(复杂数据类型)
取:JSON.parse(JSON字符串)
学生信息表案例
需求1:点击录入按钮可以将输入的数据录入进去
需求2:点击删除可以删除当前的数据
HTML代码
<h1>新增学员</h1>
<form class="info" autocomplete="off">
姓名:<input type="text" class="uname" name="uname" /> 年龄:<input
type="text"
class="age"
name="age"
/>
性别:
<select name="gender" class="gender">
<option value="男">男</option>
<option value="女">女</option>
</select>
薪资:<input type="text" class="salary" name="salary" /> 就业城市:<select
name="city"
class="city"
>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="曹县">曹县</option>
</select>
<button class="add">录入</button>
</form>
<h1>就业榜</h1>
<table>
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>薪资</th>
<th>就业城市</th>
<th>操作</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
CSS代码
* {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
color:#721c24;
}
h1 {
text-align: center;
color:#333;
margin: 20px 0;
}
table {
margin:0 auto;
width: 800px;
border-collapse: collapse;
color:#004085;
}
th {
padding: 10px;
background: #cfe5ff;
font-size: 20px;
font-weight: 400;
}
td,th {
border:1px solid #b8daff;
}
td {
padding:10px;
color:#666;
text-align: center;
font-size: 16px;
}
tbody tr {
background: #fff;
}
tbody tr:hover {
background: #e1ecf8;
}
.info {
width: 900px;
margin: 50px auto;
text-align: center;
}
.info input, .info select {
width: 80px;
height: 27px;
outline: none;
border-radius: 5px;
border:1px solid #b8daff;
padding-left: 5px;
box-sizing: border-box;
margin-right: 15px;
}
.info button {
width: 60px;
height: 27px;
background-color: #004085;
outline: none;
border: 0;
color: #fff;
cursor: pointer;
border-radius: 5px;
}
.info .age {
width: 50px;
}
JS代码
<script>
//1.读取本地存储的数据 student-data 本地存储的命名
const data = localStorage.getItem("student-data");
// 2.如果有就返回对象,没有就声明一个空数组 arr 一会渲染的时候用
const arr = data ? JSON.parse(data) : [];
// console.log(arr); //空数组
const tbody = document.querySelector("tbody");
//渲染模块函数
function render() {
// map 遍历
let trArr = arr.map(function (item, i) {
return `
<tr>
<td>${item.stuId}</td>
<td>${item.uname}</td>
<td>${item.age}</td>
<td>${item.gender}</td>
<td>${item.salary}</td>
<td>${item.city}</td>
<td>
<a href="javascript:" data-id=${i}>删除</a>
</td>
</tr>
`;
});
// console.log(trArr.join());
// 渲染拼接
tbody.innerHTML = trArr.join("");
}
render();
// 录入模块
const info = document.querySelector(".info");
// 获取表单form 里面带有name属性的元素
const items = info.querySelectorAll("[name]");
info.addEventListener("submit", function (e) {
// 阻止默认提交
e.preventDefault();
// 声明空对象
let obj = {};
// obj.stuId = arr.length + 1;
// obj.stuId = arr[arr.length - 1].stuId + 1;
obj.stuId = arr.length ? arr[arr.length - 1].stuId + 1 : 1;
// 非空判断
for (let i = 0; i < items.length; i++) {
// 如果内容为空就弹出‘内容不能为空’
// console.log(items[i].name);
const item = items[i];
if (items[i].value === "") {
return alert("内容不能为空");
}
// obj[item.name];
// obj[item.name] === obj.name obj.age
obj[item.name] = item.value;
}
console.log(obj);
// 追加
arr.push(obj);
// 存储到本地
localStorage.setItem("student-data", JSON.stringify(arr));
// 调用
render();
// 重置
this.reset();
});
// 删除模块
tbody.addEventListener("click", function (e) {
if (e.target.tagName === "A") {
// console.log(e.target.dataset.id);
// 删除
arr.splice(e.target.dataset.id, 1);
// 写入本地存储
localStorage.setItem("student-data", JSON.stringify(arr));
// 重新渲染
render();
}
});
</script>