Web Apls第五天
1.事件对象
1.获取事件对象
1.作用:
①是个对象,这个对象里有事件触发时的相关信息
2.获取:
①在事件绑定的回调函数的第一个参数就是事件对象
②一般命名为event、ev、e
3.语法:
元素.addEventlistener('click', function (e))//e事件对象
4.事件对象案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
/>
<title>02-事件对象.html</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
</style>
</head>
<body>
<button>点击点击</button>
<script>
// 获取按钮
const btn = document.querySelector('button');
btn.addEventListener('click', function (event) {
console.log(event); // 存放事件触发一瞬间的信息 - 鼠标位置信息
});
</script>
</body>
</html>
2.事件对象常用属性
1.type
①获取当前的事件类型
2.clientX/clientY
①获取光标相对于浏览器可见窗口左上角的位置
3.offsetX/offsetY
①获取光标相对于当前DOM元素左上角的位置
4.key
①用户按下的键盘键的值
②现在不提倡使用keyCode
5.事件对象常用属性案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
/>
<title>03-事件对象-常见属性</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
div{
width: 300px;
height: 400px;
background-color: aqua;
margin-left: 300px;
}
</style>
</head>
<body>
<div>点击点击</div>
<script>
// 获取按钮
const btn = document.querySelector('div');
btn.addEventListener('mousemove', function (event) {
// console.log(event.type); // 输出当前的事件类型 少用
// console.log(event.clientX,event.clientY ); // 返回 鼠标的位置-参照物 页面的左上角即可
console.log(event.offsetX,event.offsetY);// 返回鼠标的坐标,参照物 是被点击的元素的左上角
});
</script>
</body>
</html>
2.事件流
1.事件流阶段说明
①事件流指的是事件完整执行过程中的流动路径
②假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段
③简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父
④如图:
2.事件捕获和事件冒泡
1.事件冒泡概念
① 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡
②当一个元素触发事件后,会依次向上调用所有父级元素的同名事件
③事件冒泡是默认存在的
2.事件捕获概念
1.概念:
① 从DOM的根元素开始去执行对应的事件 (从外到里)事件捕获需要写对应代码才能看到效果
2.语法:
DOM.addEventListener(事件类型, 事件处理函数, 是否使用捕获机制)
3.说明
①addEventListener第三个参数传入true代表是捕获阶段触发(很少使用)
②若传入false代表冒泡阶段触发,默认就是false
③若是用 L0 事件监听,则只有冒泡阶段,没有捕获
4..事件捕获和冒泡案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
/>
<title>01-事件流动捕获和冒泡.html</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
div {
width: 200px;
height: 200px;
padding: 20px;
overflow: hidden;
}
.a {
background-color: red;
}
.b {
background-color: blue;
}
.c {
background-color: green;
}
</style>
</head>
<body>
<div class="a">
爷
<div class="b">
爸
<div class="c">儿</div>
</div>
</div>
<script>
const a = document.querySelector('.a');
a.addEventListener(
'click',
function () {
console.log('a');
},
true
); // 捕获
const b = document.querySelector('.b');
b.addEventListener(
'click',
function () {
console.log('b');
},
true
); // 捕获
const c = document.querySelector('.c');
c.addEventListener(
'click',
function () {
console.log('c');
},
false
);
/*
事件流动
1 给多个父子结构的标签绑定事件, 先点击了子元素, 产生事件流动
2 事件流动 分成了两个阶段
1 捕获阶段 父节点 流动到 子节点
2 冒泡节点 子节点 流动到 父节点 默认
3 例子:
人 跳水
1 水上 水里面 不断下沉
4 事件流动方向 默认是 使用了冒泡 - 点击儿子标签 触发 儿子->父亲->爷爷
3 我们可以修改触发事件 让它选择使用 捕获阶段还是冒泡阶段(默认)
addEventListener 可以选择使用冒泡还是捕获
addEventListener(事件类型,事件处理函数,捕获还是冒泡(默认值 false,可以省略))
addEventListener("click",function(){}, true )
4 总结
1 捕获和 冒泡 特点 了解
2 默认情况 冒泡 如果想要修改 可以 addEventListener 第三个参数 传入 true即可
3 以后的代码开发过程中,还是继续使用默认的 冒泡阶段
*/
</script>
</body>
</html>
3.阻止事件流动
1.作用
①默认就有冒泡模式的存在,所以容易导致事件影响到父级元素
②若想把事件就限制在当前元素内,就需要阻止事件流动
③阻止事件流动需要拿到事件对象
④此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效
2.语法:
事件对象.stopPropagetion()
3.鼠标经过事件:
①mouseover 和 mouseout 会有冒泡效果
②ouseenter 和 mouseleave 没有冒泡效果(推荐)
4.阻止默认行为:
①比如链接点击不跳转,表示表单域的没有提交
5.语法:
e.preventDefault()
4.两种注册事件的区别
1.传统on注册(L0)
①同一个对象,后面注册的事件会覆盖前面注册(同一个事件
②直接使用null覆盖偶就可以实现事件的解绑
③都是冒泡阶段执行的
2.事件监听注册(L2)
①语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)
②后面注册的事件不会覆盖前面注册的事件(同一个事件)
③可以通过第三个参数去确定是在冒泡或者捕获阶段执行
④必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
⑤匿名函数无法被解绑
3.事件委托
1.作用
①事件委托是利用事件流的特征解决一些开发需求的知识技巧
2.总结
①优点:给父级元素加事件(可以提高性能)
②原理:事件委托其实是利用事件冒泡的特点, 给父元素添加事件,子元素可以触发
③实现:事件对象.target 可以获得真正触发事件的元素
3.事件委托案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"
/>
<title>06-事件委托感受.html</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul{
width: 500px;
background-color: aqua;
padding: 50px;
}
li{
background-color: yellow;
height: 50px;
}
a{
background-color: sandybrown;
}
</style>
</head>
<body>
<ul>
<li><a href="#">1</a></li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
// 点击那个一li标签 颜色设置为红色
// 以前获取到每一个li标签 数组 遍历他们 按个绑定点击事件
// const liList=document.querySelectorAll("li");
// for (let index = 0; index < liList.length; index++) {
// liList[index].addEventListener("click",function () {
// this.style.backgroundColor="red"
// })
// }
// 事件委托
// 本来想要给li标签绑定事件实现业务
// 把事件绑定写在 父元素上 把li标签应该要做的事情 委托给父元素来做!
const ul=document.querySelector("ul");
ul.addEventListener("click",function (event) {
// event.target 有可能是ul标签,有可能是li标签,还有可能是 a标签
// 一会再来解决这个问题。
event.target.style.backgroundColor="red";// 不够完美的
// event.target 你当前点击的是哪个标签(点击最深最底层的那个标签即可)
// console.log(event.target);// 获取到被点击的li标签
})
</script>
</body>
</html>
4.渲染学生信息案例
1.需求
2.实现案例
<!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>08-综合案例-完成删除功能</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 arr = [ ];
const tbody = document.querySelector('tbody');
// 2 给 录入绑定点击事件
const add = document.querySelector('.add');
const uname = document.querySelector('.uname');
const age = document.querySelector('.age');
const gender = document.querySelector('.gender');
const salary = document.querySelector('.salary');
const city = document.querySelector('.city');
// 1.2 根据数组渲染页面
renderTableByArr();
// 2 按钮绑定点击事件
add.addEventListener('click', function () {
// 2.1 创建一个新的对象 把表单数据都合并到对象中
const data = {
// 学号
id: Date.now(),
// 姓名
uname: uname.value,
// 年龄
age: age.value,
// 性别
gender: gender.value,
// 薪资
salary: salary.value,
// 就业城市
city: city.value,
};
// 老师打了一个 断点 来验证 上面的代码 没有写错
// 2.2 给数组插入新的元素
arr.push(data);
// 2.3 数组发生改变 重新调用渲染页面的函数
renderTableByArr();
// 2.4 表单数据清空
uname.value = '';
age.value = '';
gender.value = '男';
salary.value = '';
city.value = '北京';
});
// 3 tbody绑定点击事件,同时判断被点击的是不是 del 删除标签
tbody.addEventListener('click', function (event) {
// 3.1 判断当前点击的是不是a标签
if (event.target.nodeName === 'A') {
// <a data-index="2" href="javascript:" class="del">删除</a>
// 获取到a标签 上存放的 index
// event.target = a标签的dom元素
// console.dir(event.target.dataset.index)
const index = event.target.dataset.index;
// 3.3 执行数组删除元素
arr.splice(index,1);
// 3.4 调用根据数组渲染页面的函数
renderTableByArr();
}
});
// 根据数组渲染表格
function renderTableByArr() {
let html = ``;
for (let index = 0; index < arr.length; index++) {
html += `
<tr>
<td>${arr[index].id}</td>
<td>${arr[index].uname}</td>
<td>${arr[index].age}</td>
<td>${arr[index].gender}</td>
<td>${arr[index].salary}</td>
<td>${arr[index].city}</td>
<td>
<a data-index="${index}" href="javascript:" class="del">删除</a>
</td>
</tr>
`;
}
// 把生成的tr插入到 tbody中
tbody.innerHTML = html;
}
</script>
</body>
</html>
3.示例图