事件对象
也是个对象,这个对象里有事件触发时的相关信息 例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息
获取事件对象
在事件绑定的回调函数的第一个参数就是事件对象 一般命名为event、ev、e
事件对象常用属性
- type 获取当前的事件类型
let div = document.querySelector('div');
div.addEventListener('click', function(e) {
//输出为 click
console.log(e.type);
})
- clientX/clientY 获取光标相对于浏览器可见窗口左上角的位置
div.addEventListener('click', function(e) {
//相距浏览器左边,上边的距离
console.log(e.clientX, e.clientY);
})
- offsetX/offsetY 获取光标相对于当前DOM元素左上角的位置
let div = document.querySelector('div');
div.addEventListener('click', function(e) {
//相距dom元素左边,上边的距离
console.log(e.offsetX, e.offsetY);
})
- key 用户按下的键盘键的值 现在不提倡使用keyCode
window.addEventListener('keydown', function(e) {
//获取键盘的值 例如按下 enter键,值为Enter
console.log(e.key);
})
鼠标跟随案例
<!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>
img {
position: absolute;
/* 移动自身宽高的一半,此时鼠标在图片垂直居中位置 */
transform: translate(-50%, -50%);
}
body {
height: 100vh;
overflow: hidden;
/* 隐藏鼠标 */
cursor: none;
}
</style>
</head>
<body>
<img src="./images/天使.gif" alt="">
<script>
const img = document.querySelector('img');
document.body.addEventListener('mousemove', function(e) {
//图片的坐标和鼠标在浏览器的位置相等
img.style.left = e.clientX + 'px';
img.style.top = e.clientY + 'px';
})
</script>
</body>
</html>
回车发布微博案例
<!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>
<textarea cols="30" rows="10"></textarea>
<button>发布</button>
<h1></h1>
<script>
let text = document.querySelector('textarea'),
btn = document.querySelector('button'),
h1 = document.querySelector('h1');
btn.addEventListener('click', function(e) {
//trim()方法是给字符串前后去掉空白符
if (text.value.trim() === '') {
return;
}
h1.innerHTML = text.value;
})
text.addEventListener('keydown', function(e) {
//e.key返回的值是字符串
if (e.key === 'Enter') {
btn.click();
//按下回车键不换行,取消文本域的默认行为
// e.preventDefault();
}
})
</script>
</body>
</html>
事件流
事件流指的是事件完整执行过程中的流动路径
说明:假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段 简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父
事件冒泡
当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡。
- 简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件
- 事件冒泡是默认存在的
事件捕获
从DOM的根元素开始去执行对应的事件 (从外到里)
代码:
说明:
- addEventListener第三个参数传入true代表是捕获阶段触发(很少使用)
- 若传入false代表冒泡阶段触发,默认就是false
- 若是用 L0 事件监听,则只有冒泡阶段,没有捕获
阻止事件流动
- 因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素
- 若想把事件就限制在当前元素内,就需要阻止事件流动
- 阻止事件流动需要拿到事件对象
语法:
此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效。
鼠标经过事件
- mouseover 和 mouseout 会有冒泡效果
- mouseenter 和 mouseleave 没有冒泡效果(推荐)
阻止默认行为
比如链接点击不跳转,表单域的不提交
语法:
代码:
两种注册事件的区别:
传统on注册(L0)
- 同一个对象,后面注册的事件会覆盖前面注册(同一个事件)
- 直接使用null覆盖就可以实现事件的解绑
- 都是冒泡阶段执行的
事件监听注册(L2)
语法: addEventListener(事件类型, 事件处理函数, 是否使用捕获)
- 后面注册的事件不会覆盖前面注册的事件(同一个事件)
- 可以通过第三个参数去确定是在冒泡或者捕获阶段执行
- 必须使用removeEventListener(事件类型, 事件处理函数, 获取捕获或者冒泡阶段)
- 匿名函数无法被解绑
冒泡事件解除绑定案例
<!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>
<button>点击</button>
<script>
const btn = document.querySelector('button');
function getNu() {
document.body.style.backgroundColor = 'blue';
}
function getNum() {
console.log('111');
}
btn.addEventListener('click', getNu);
btn.addEventListener('click', getNum);
//解除绑定事件和业务逻辑,只解除了一个事件和一个业务逻辑
btn.removeEventListener('click', getNum);
</script>
</body>
</html>
事件委托
事件委托是利用事件流的特征解决一些开发需求的知识技巧
总结: 优点:给父级元素加事件(可以提高性能) 原理:事件委托其实是利用事件冒泡的特点, 给父元素添加事件,子元素可以触发 实现:事件对象.target 可以获得真正触发事件的元素
<!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>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
height: 100vh;
}
ul {
width: 100px;
height: 95px;
padding: 0px 10px;
border: 1px solid black;
list-style-type: none;
border-radius: 10px;
}
li {
padding: 5px 0px;
cursor: pointer;
}
</style>
</head>
<body>
<ul>
<li>回到首页</li>
<li>到达底部</li>
<li>刷新</li>
</ul>
<script>
let ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
e.target.style.backgroundColor = 'red';
})
</script>
</body>
</html>
获取当前事件触发的dom元素名称
语法:
<!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>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
height: 100vh;
}
ul {
width: 100px;
height: 95px;
padding: 0px 10px;
border: 1px solid black;
list-style-type: none;
border-radius: 10px;
}
li {
padding: 5px 0px;
cursor: pointer;
}
</style>
</head>
<body>
<ul>
<li>回到首页</li>
<li>到达底部</li>
<li>刷新</li>
</ul>
<script>
let ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
console.log(e.target.nodeName);//输出LI
})
</script>
</body>
</html>
渲染学生信息案例
数据驱动视图
需求:点击录入按钮,可以增加学生信息
<!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>
let arr = [];
const tbody = document.querySelector('tbody'),
add = document.querySelector('.add'),
uname = document.querySelector('.uname'),
age = document.querySelector('.age'),
gender = document.querySelector('.gender'),
salary = document.querySelector('.salary'),
city = document.querySelector('.city');
//创建数组的对象
add.addEventListener('click', function() {
const Obj = {
id: Date.now(),
uname: uname.value,
age: age.value,
gender: gender.value,
salary: salary.value,
city: city.value
}
//将对象推进arr数组里
arr.push(Obj); //此时输出的是数组的长度
//对象传入后刷新数据,将数据传入表格中
getTr();
uname.value = '';
age.value = '';
gender.value = '男';
salary.value = '';
city.value = '北京';
})
tbody.addEventListener('click', function(e) {
if (e.target.nodeName === 'A') {
let num = e.target.dataset.num;
arr.splice(num, 1)
}
getTr()
})
//封装创建tbody里的标签功能
function getTr() {
let html = '';
for (let i = 0; i < arr.length; i++) {
html += `
<tr>
<td>${arr[i].id}</td>
<td>${arr[i].uname}</td>
<td>${arr[i].age}</td>
<td>${arr[i].gender}</td>
<td>${arr[i].salary}</td>
<td>${arr[i].city}</td>
<td>
<a href="javascript:" class="del" data-num=${i}>删除</a>
</td>
</tr> `
}
tbody.innerHTML = html;
}
</script>
</body>
</html>