const和let的区别
早些时候js 声明变量 只能使用 var
es6 (新版本的js) 出现之后,只使用 let 或者const
let 声明的变量,可以被修改
const 声明的变量 ,不可以被修改。const是常量,固定不变的
const 作用:
-
在程序设计的时候,如果发现有一些数据,永远不会被更改,优先使用const
复杂类型的数据 补充
1.普通类型的数据 ,直接写 =, 表示修改数据,报错
const num1 = 1
num1 = 2
console.log(num1); 报错
2.复杂类型的数据 ,直接写 =, 表示修改,报错
3.复杂类型的数据,写 = 相对于重新开辟新空间
const arr = []
arr.push(1) //新增一个元素。但是没有修改过数组的地址
arr = 234 //报错 开辟了新开间
console.log(arr);
总结:const 不能被修改的判断的方式:看它有没有写 = 号即可,或者自增自减
能使用const就不用let 。当不知道什么时候用const,就使用 let
事件高级
一、事件对象(重点)
1.定义
也是一个对象,事件触发的那一瞬间所包含的信息,比如说鼠标坐标的信息;键盘按下信息
2.获取事件对象
在事件绑定的回调函数第一个形参就是事件对象
<title>事件对象</title>
</head>
<body>
<button>点击</button>
<script>
let button = document.querySelector('button')
// 事件监听
button.addEventListener('click',function (event) {
console.log(event);
})
</script>
3.事件对象常见属性
1.type 输出当前的事件类型,比较少用
2.clientX, clientY 返回鼠标的位置,参照物- 是页面的左上角
3.offsetX, offsetY 返回鼠标的位置,参照物-是被点击的元素的左上角
4.key 用户当下按下的键盘的值
小鸟跟随鼠标案例
需求:一张图片一直跟着鼠标移动
<title>事件对象常见属性</title>
<style>
img {
width: 50px;
position: absolute;
}
</style>
</head>
<body>
<img src="./birdie.png" alt="" />
<script>
// 获取img dom元素
let img = document.querySelector("img");
// 事件监听,添加事件对象
img.addEventListener("mousemove", function (event) {
let left = event.clientX
let top = event.clientY
img.style.left = left + 'px';
img.style.top = top + 'px' ;
});
</script>
</body>
按下回车发布微博案例
需求:按下回车键盘,可以发布信息
<!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>事件对象key练习</title>
<style>
textarea {
width: 600px;
height: 100px;
}
ul {
list-style: none;
}
</style>
</head>
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul>
<!-- <li>苹果</li> -->
</ul>
<script>
// 获取ul 元素
let ul = document.querySelector("ul");
// console.log(ul);
// 获取文本域的元素
let textarea = document.querySelector("textarea");
// console.log(textarea);
// 获取发布按钮
let button = document.querySelector("button");
// 给发布注册事件
button.addEventListener("click", function (event) {
// 新建li节点
let li = document.createElement("li");
li.innerText = textarea.value;
ul.appendChild(li);
textarea.value = ''
});
// 在文本域中按下回车键也是实现发布按钮
textarea.addEventListener("keydown", function (event) {
if (event.key === "Enter") {
// console.log('执行和按钮一样的功能');
event.preventDefault() //组织浏览器标签的默认行为
let li = document.createElement("li");
li.innerText = textarea.value;
ul.appendChild(li);
textarea.value = ''
}
});
</script>
</body>
</html>
补充:event.preventDefault() //组织浏览器标签的默认行为
二、事件流
1.事件流和两个阶段说明
事件流:指的是事件完整执行过程中的流动路径 简单来说给多个父子结构的标签绑定事件,先点击了子元素,产生事件流动
捕获阶段 :是从父元素到子元素
冒泡阶段:是从子元素到父元素
事件流动方向 默认是使用了冒泡
<title>事件流动捕获和冒泡</title>
<style>
div {
width: 400px;
height: 400px;
padding: 20px;
overflow: hidden;
}
.a {
background-color: pink;
}
.b {
background-color: yellow;
}
.c {
background-color: purple;
}
</style>
</head>
<body>
<div class="a">
爷爷
<div class="b">
爸爸
<div class="c">儿子</div>
</div>
</div>
<script>
let a = document.querySelector(".a");
a.addEventListener("click", function () {
console.log('a 爷爷');
});
let b = document.querySelector(".b");
b.addEventListener("click", function () {
console.log('b 爸爸');
});
let c = document.querySelector(".c");
c.addEventListener("click", function () {
console.log('c 儿子');
});
</script>
当点击儿子的时候,顺序是从儿子 ->爸爸 ->爷爷
补充
addEventListener可以修改触发事件,让它选择使用捕获还是冒泡(默认)
addEventListener(事件类型,事件处理函数,捕获还是冒泡(默认值是false ,可以省略))
addEventListener(‘click’,function(){},true)捕获
以后是代码开发过程中,很少使用捕获阶段,还是继续使用默认的冒泡阶段
2.阻止事件冒泡
原因
因为默认就有冒泡模式的存在,所以容易导致事件影响到父元素,所以如果想要把事件限制在当前元素内,就需要阻止事件流动
语法
event.stopPropagation()
<title>阻止事件冒泡</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
div {
width: 400px;
height: 400px;
padding: 20px;
overflow: hidden;
}
.a {
background-color: pink;
}
.b {
background-color: yellow;
}
.c {
background-color: purple;
}
p {
width: 400px;
height: 400px;
background-color: aqua;
}
</style>
</head>
<body>
<p>1</p>
<div class="a">
爷爷
<div class="b">
爸爸
<div class="c">儿子</div>
</div>
</div>
<script>
// 需求:点击不同的div显示不同的颜色
// 方式一:因为事件流的默认方向是冒泡阶段,比较粗暴的解决方式可以在每个div后面加上true,改变事件流动的方向
// 方式二:在事件对象中,event找到一个方法,阻止冒泡 event.stopPropagation()
let p = document.querySelector('p')
// console.log(p);
let a = document.querySelector(".a");
a.addEventListener("click", function () {
p.style.backgroundColor = 'pink'
// 设置p文本内容 = 文本内容+1 需要注意转换隐式模式
p.innerText = +p.innerText + 1
console.log("a 爷爷");
},true);
let b = document.querySelector(".b");
b.addEventListener("click", function (event) {
p.style.backgroundColor = 'yellow'
p.innerText = +p.innerText + 10
//阻止事件冒泡
event.stopPropagation()
console.log("b 爸爸");
},true);
let c = document.querySelector(".c");
c.addEventListener("click", function (event) {
p.style.backgroundColor = 'purple'
p.innerText = +p.innerText + 100
//阻止事件冒泡
event.stopPropagation()
console.log("c 儿子");
});
</script>
3.阻止标签的默认行动
3.1 a 标签的点击跳转
event.preventDefault() //阻止浏览器标签的默认行为
3.2 form表单中button点击刷新行为
- 解决方式一:阻止默认行为 - form表单 有一个submit事件。理解提交表单的触发,-点击按钮的时候触发
- 解决方式二 :给button按钮绑定点击事件,也去阻止试试
- 解决方式三:给button按钮添加一个type ='button'
- 解决方式四:换成input 标签type = 'button'
- 解决方式五:把button移出form 表单的区域
案例代码
<title>阻止标签的默认行为</title>
</head>
<body>
<a href="http://baidu.com">百度</a><br />
<form>
<!--方式3 <button type="button">点击自动刷新</button> -->
<!--方式4 <input type="button" value="点击我会刷新"> -->
</form>
<!-- 方式5:把button移出form 表单的区域 -->
<button>不会再刷新</button>
</body>
<script>
let a = document.querySelector("a");
let button = document.querySelector("button");
let form = document.querySelector('form')
a.addEventListener("click", function (event) {
// 阻止标签默认行为
event.preventDefault();
console.log("点击事件触发了");
});
// 方式1: form.addEventListener("submit", function (event) {
// event.preventDefault();
// console.log("点击刷新");
// });
//方式2 button.addEventListener("click", function (event) {
// event.preventDefault();
// console.log("点击刷新");
// });
//
</script>
3.3鼠标右键弹出菜单
contextmenu 鼠标右键
三、事件委托(重点)
1.定义
利用事件流的特征来解决一些开发需求的技巧
2.原理
事件委托其实就是利用了事件冒泡的特点。给父元素添加事件,子元素就可以触发
3.优点
给父元素添加事件,可以提高性能
4.实现
event.target 你当前点击的是哪个标签,(点击最深层的那个标签)
5.优化
event.target.nodeName 当前点击的元素的标签名 大写
渲染学生信息案例
需求如下
效果图
思路分析图
案例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>学生信息综合案例</title>
<style>
* {
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 {
width: 80px;
height: 25px;
outline: none;
border-radius: 5px;
border: 1px solid #b8daff;
padding-left: 5px;
}
.info button {
width: 60px;
height: 25px;
background-color: #004085;
outline: none;
border: 0;
color: #fff;
cursor: pointer;
border-radius: 5px;
}
.info .age {
width: 50px;
}
</style>
</head>
<body>
<h1>新增学员</h1>
<div class="info">
姓名:<input type="text" class="uname" /> 年龄:<input
type="text"
class="age"
/>
性别:
<select name="gender" id="" class="gender">
<option value="男">男</option>
<option value="女">女</option>
</select>
薪资:<input type="text" class="salary" /> 就业城市:<select
name="city"
id=""
class="city"
>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="广州">广州</option>
<option value="深圳">深圳</option>
<option value="曹县">曹县</option>
</select>
<button class="add">录入</button>
</div>
<h1>就业榜</h1>
<table>
<thead>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>薪资</th>
<th>就业城市</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- <tr>
<td>1</td>
<td>这是名称</td>
<td>这是年龄</td>
<td>这是性别</td>
<td>这是工资</td>
<td>这是所在城市</td>
<td>
<a href="javascript:" class="del">删除</a>
</td>
</tr> -->
</tbody>
</table>
<script>
/* 需求:添加数据,删除数据 */
// 1.1设置一个数组,对象存放表格要显示的数据 方便管理
let array = [];
// 2.给录入 绑定点击事件
// 获取录入
let button = document.querySelector(".add");
// 获取tbody
let tbody = document.querySelector("tbody");
// 获取姓名
let uname = document.querySelector(".uname");
// 获取年龄
let age = document.querySelector(".age");
// 获取性别
let gender = document.querySelector(".gender");
// 获取薪资
let salary = document.querySelector(".salary");
// 获取城市
let city = document.querySelector(".city");
// 1.3调用渲染页面的函数
renderByArr();
// 2.给按钮注册事件
button.addEventListener("click", function () {
// 2.1把表单数据合并到一个新的对象中
let newDate = {
// 随机生成时间,时间戳
num: +new Date(),
uname: uname.value,
age: age.value,
gender: gender.value,
salary: salary.value,
city: city.value,
};
// 2.2给数组新增对象数据
array.push(newDate);
// 2.3数组发生改变后,重新调用渲染页面
renderByArr();
// console.log(array);
// 2.4点击发布后数据清零
uname.value = "";
age.value = "";
gender.value = "男";
salary.value = "";
city.value = "北京";
});
// 删除数据
// 3.tbody绑定点击事件,同时判断被点击的是不是删除标签
tbody.addEventListener("click", function (event) {
// 3.1 事件触发了先判断当前点击的是不是删除
if (event.target.nodeName === "A") {
// date-index 自定义属性
// 3.2 在点击删除标签的时候,知道当前点击的是第几个元素
// <a date-index = '2' href="javascript:" class="del">删除</a>
// 获取到a标签上的存放的index
const index = event.target.dataset.index;
// 3.3数组删除元素
array.splice(index, 1);
// 3.4数组发生改变后,重新调用渲染页面
renderByArr();
}
});
// 1.1根据数组渲染表格
function renderByArr() {
// 拼接开头
let html = ``;
for (let index = 0; index < array.length; index++) {
html += `<tr>
<td>${array[index].num}</td>
<td>${array[index].uname}</td>
<td>${array[index].age}</td>
<td>${array[index].gender}</td>
<td>${array[index].salary}</td>
<td>${array[index].city}</td>
<td>
<a date-index${index} href="javascript:" class="del">删除</a>
</td>
</tr>`;
}
// 把生成的tr插入到tbody中
tbody.innerHTML = html;
}
</script>
</body>
</html>