事件对象
- 事件对象是什么?
也是个对象,这个对象里有事件触发时的相关信息。
例如:鼠标点击事件中,事件对象就存了鼠标点在哪个位置等信息.
- 如何获取? 在事件绑定的回调函数的第一个参数就是事件对象。 一般命名为event、ev、e。
元素.addEventListener('click',function(事件对象){
})
<body>
<button>1111111</button>
<script>
const btn = document.querySelector("button");
// 事件对象 元素.addEventListener('click',function(事件对象); 事件对象一般命名为event、ev、e
btn.addEventListener('click',function(event){
console.log(event)
})
</script>
</body>
部分常用属性
| 属性 | 说明 |
|---|---|
| type | 获取当前的事件类型 |
| clientX / clientY | 获取光标相对于浏览器可见窗口左上角的位置 |
| offsetX / offsetY | 获取光标相对于当前DOM元素左上角的位置 |
| key | 用户按下的键盘键的值。现在不提倡使用keyCode |
示例:
<body>
<div>点击点击</div>
<textarea name="" id="" cols="30" rows="10"></textarea>
<script>
// 获取按钮
const btn = document.querySelector('div');
//获取文本域
const textarea = document.querySelector("textarea");
btn.addEventListener('mousemove', function (event) {
// console.log(event.type); // 输出当前的事件类型 少用
// console.log(event.clientX,event.clientY ); // 返回 鼠标的位置-参照物 页面的左上角即可
console.log(event.offsetX,event.offsetY);// 返回鼠标的坐标,参照物 是被点击的元素的左上角
});
//绑定键盘事件
textarea.addEventListener("keydown",function(){
console.log(event.key) //显示鼠标按下的键
})
</script>
</body>
小鸟跟随鼠标移动案例
要求 :小鸟图标跟随着鼠标移动 。
<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 {
width: 50px;
height: 50px;
/* background-color: pink; */
position: fixed;
/* 移动自身宽度和高度的一半,让图片在鼠标指到的位置中心 */
transform: translate(-50%, -50%);
}
body {
/* 注意 body也是块级元素 没有设置高度的话 默认由内容撑开,所以给他加上高度是视口的100% */
height: 100vh;
/* 隐藏鼠标 */
cursor: none;
}
</style>
</head>
<body>
<!-- 要求 小鸟图标跟随着鼠标移动 -->
<img src="./img/微信图片_20220411164226.png" alt="">
<script>
let img = document.querySelector("img");
//鼠标在页面移动 绑定触发事件
document.body.addEventListener('mousemove', function (event) {
//修改div定位之后的位置调整 用clientX/clientY 套进去
img.style.top = `${event.clientY}px`
img.style.left = `${event.clientX}px`
})
</script>
</body>
微博发布案例-回车键发布
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>发布</button>
<ul>
</ul>
<script>
let textarea = document.querySelector("textarea");
let button = document.querySelector("button");
let ul = document.querySelector("ul");
button.addEventListener('click', function () {
// 优化 :判断当前文本域的内容是不是空字符串,空字符串就发布不了
//.trim() 获取到的是清除空格后的文本
if (textarea.value.trim()==="") {
return
}
let li = document.createElement('li');
li.innerHTML = `${textarea.value}`;
ul.appendChild(li);
textarea.value = "";
})
//绑定键盘按下事件 当键盘按回车 发布内容到li
textarea.addEventListener("keydown", function (event) {
if (event.key === "Enter") {
// let li = document.createElement('li');
// li.innerHTML = `${textarea.value}`;
// ul.appendChild(li);
// textarea.value = "";
// 以上发布内容的代码可以优化 可以直接调用 发布的点击事件
button.click();
}
})
</script>
</body>
事件流
事件流指的是事件完整执行过程中的流动路径。
说明:假设页面里有个div,当触发事件时,会经历两个阶段,分别是捕获阶段、冒泡阶段。 简单来说:捕获阶段是 从父到子 冒泡阶段是从子到父。
事件冒泡
概念:
- 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发。这一过程被称为事件冒泡。
- 简单理解:当一个元素触发事件后,会依次向上调用所有父级元素的同名事件 事件冒泡是默认存在的。
- js默认冒泡事件:addEventListener("click",function(){},false) ;
事件捕获
概念:
-
从DOM的根元素开始去执行对应的事件 (从外到里)。
-
事件捕获需要写对应代码才能看到效果。
说明:
- addEventListener第三个参数传入true代表是捕获阶段触发(很少使用)。
- 若传入false代表冒泡阶段触发,默认就是false
- 若是用 L0 事件监听,则只有冒泡阶段,没有捕获
-
addEventListener("click",function(){},true), 谁加了 true,那他的点击事件会优先触发
<body>
<div class="one">a
<div class="two">b
<div class="three">c</div>
</div>
</div>
<script>
//事件流动分为两个阶段:
//1.捕获阶段 是 父节点 流动到 子节点
//2.冒泡阶段 是 子节点 流动到 父节点
//我们可以修改触发事件 让他选择使用捕获阶段还是冒泡阶段
//addEventListener 可以选择使用冒泡还是捕获
//写法:addEventListener(事件类型,事件处理函数,捕获还是冒泡(默认值false,可以省略)
//addEventListener("click",function(){},true), 谁加了 true,那他的点击事件会优先触发
const a = document.querySelector(".one")
const b = document.querySelector(".two")
const c = document.querySelector(".three")
a.addEventListener("click", function () {
console.log(a)
}, true) //true 会优先执行该点击事件
b.addEventListener("click", function () {
console.log(b)
})//默认是false,可以省略不写
c.addEventListener("click", function () {
console.log(c)
})
</script>
</body>
阻止冒泡
在事件对象中 event 找到一个方法 停止冒泡 event.stopPropagation();
1.因为默认就有冒泡模式的存在,所以容易导致事件影响到父级元素。 2.若想把事件就限制在当前元素内,就需要阻止事件流动。 3.阻止事件流动需要拿到事件对象。
4.此方法可以阻断事件流动传播,不光在冒泡阶段有效,捕获阶段也有效。
语法:
事件对象. event.stopImmediatePropagation();
示例:
<script>
let num = document.querySelector(".num")
const a = document.querySelector(".one")
const b = document.querySelector(".two")
const c = document.querySelector(".three")
num.innerText =1;
a.addEventListener("click", function () {
num.style.backgroundColor= 'aqua';
num.innerText = +num.innerText+1;
}, )
b.addEventListener("click", function () {
num.style.backgroundColor= 'pink';
num.innerText = +num.innerText + 10;
//阻止事件冒泡
event.stopImmediatePropagation();
})
c.addEventListener("click", function (event) {
num.style.backgroundColor= 'blueviolet';
num.innerText = +num.innerText + 100;
//阻止事件冒泡
event.stopImmediatePropagation();
})
</script>
</body>
鼠标经过事件: mouseover 和 mouseout 会有冒泡效果 mouseenter 和 mouseleave 没有冒泡效果(推荐)
阻止标签默认行为
阻止默认行为,比如链接点击不跳转,表单域的不提交。
语法:
语法.event.preventDefault()
清除表单和超链接跳转默认样式示例:
<body>
<a href="https://www.baidu.com/">百度</a>
<form action="">
<button type="button">点击按钮 会自动刷新</button>
<!--input 标签 type= “button” 不会自动刷新 -->
<input type="button">
</form>
<script>
//event.preventDefault();阻止标签默认样式
const a = document.querySelector("a")
const button = document.querySelector("button")
const form =document.querySelector("form")
/*
1. a标签的点击跳转
2.form 表单中的button 点击刷新行为
1.阻止默认行为 :form表单 有一个submit事件,理解提交表单的触发。
2.给 button绑定点击事件 阻止
3.给button 添加个 type=“button” 属性
4.换成 input 标签 type= “button”
5.把button 移出form表单区域
*/
//阻止a点击跳转功能
a.addEventListener('click', function (event) {
event.preventDefault();
console.log(11111)
})
//阻止按钮点击刷新功能 1
// form.addEventListener("submit", function (enevt) {
// event.preventDefault();
// })
//阻止按钮点击刷新功能 2
// button.addEventListener('click', function (event) {
// event.preventDefault();
// })
</script>
</body>
鼠标右键自定义菜单-案例
<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>
body{
height: 100vh;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
ul {
width: 150px;
height: 200px;
list-style: none;
text-align: center;
line-height: 50px;
border: 1px solid #999;
display: none;
position: fixed;
}
li {
height: 50px;
border-bottom: 1px solid #999;
}
li:hover {
background-color: skyblue;
color: #fff;
/* 鼠标光标变手指 */
cursor: pointer;
}
</style>
</head>
<body>
<ul>
<li>添加图片</li>
<li>切换壁纸</li>
<li>下载壁纸</li>
<li>设置</li>
</ul>
<script>
let ul = document.querySelector("ul");
//1.给页面绑定鼠标右键按下事件
document.body.addEventListener('contextmenu', function (event) {
//清除页面鼠标默认样式跳出来的
event.preventDefault();
// 定义两个变量是鼠标移动的坐标 获取的坐标是相对于浏览器可见窗口左上角的位置
const left = event.clientX;
const top = event.clientY;
//ul标签鼠标右键按下 显示,及固定定位的位置,把上面获取到的位置套进去就行,因为获取到的只是数字,没有单位,记得加px,
ul.style.display = 'block';
ul.style.left = left + 'px';
ul.style.top = top + 'px';
});
//2.再给页面绑定鼠标左键按下时 ul标签消失
document.body.addEventListener('click',function(){
ul.style.display='none'
})
</script>
</body>
事件委托
**事件委托 **是利用事件流的特征解决一些开发需求的知识技巧。
总结:
- 优点:给父级元素加事件(可以提高性能)。
- 原理:事件委托其实是利用事件冒泡的特点, 给父元素添加事件,子元素可以触发。
- 实现:事件对象.target 可以获得真正触发事件的元素。
示例:
<body>
<ul>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
<li>1</li>
</ul>
<script>
let ul = document.querySelector("ul");
ul.addEventListener("click",function(event){
//直接这样做不完美,因为点ul也会变红
// event.target.style.backgroundColor="red";
//只有点击li标签才触发
//event.target.nodeName 显示当前点击元素的标签名字,大写的
//要求只有鼠标点到的位置 标签名是li 他的颜色才变红。
if(event.target.nodeName==="LI"){
event.target.style.backgroundColor="red";
}
})
</script>
</body>
录入学员信息-综合案例
<!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 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标签 (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>
滚动事件
滚动事件:当页面进行滚动时触发的事件。
-
很多网页需要检测用户把页面滚动到某个区域后做一些处理, 比如固定导航栏,比如返回顶部。
-
事件名:scroll 监听整个页面滚动:
给 window 或 document 添加 scroll 事件。 监听某个元素的内部滚动直接给某个元素加即可。
滚动的距离
这个代码可以获取当前页面滚动的距离:
document.documentElement.scrollTop
示例:
<script>
window.addEventListener("scroll",function(){
//这个代码可以获取当前页面滚动的距离
console.log(document.documentElement.scrollTop)
})
</script>
固定导航案例
<!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>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
header{
height: 250px;
background-color: aqua;
}
nav{
height: 250px;
background-color: blueviolet;
}
.fixed{
position: fixed;
top: 0;
left: 0;
width: 100%;
}
div{
background-color: pink;
}
</style>
</head>
<body>
<header></header>
<nav ></nav>
<div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
<li>13</li>
<li>14</li>
<li>15</li>
<li>16</li>
<li>17</li>
<li>18</li>
<li>19</li>
<li>20</li>
<li>21</li>
<li>22</li>
<li>23</li>
<li>24</li>
<li>25</li>
<li>26</li>
<li>27</li>
<li>28</li>
<li>29</li>
<li>30</li>
<li>31</li>
<li>32</li>
<li>33</li>
<li>34</li>
<li>35</li>
<li>36</li>
<li>37</li>
<li>38</li>
<li>39</li>
<li>40</li>
<li>41</li>
<li>42</li>
<li>43</li>
<li>44</li>
<li>45</li>
<li>46</li>
<li>47</li>
<li>48</li>
<li>49</li>
<li>50</li>
</ul>
</div>
<script>
// 要求:鼠标滑动到导航栏的时候 导航栏固定定位在顶部
// 获取 导航栏 和 头部
const nav =document.querySelector("nav")
const header =document.querySelector("header");
//给窗口绑定鼠标滚动事件
window.addEventListener("scroll",function(event){
//定义一个 代表是鼠标滚动的位置
const scrollTop=document.documentElement.scrollTop;
//当滚动位置过了头部的时候,相当于过了头部的高度时
if(scrollTop>=250){
//给导航栏加个类名, 这个类名是css原先就设置好的固定定位样式等
nav.classList.add('fixed');
//给头部加个下外边距是自己的高度 因为导航固定定位的时候脱标了,会挡住下面的内容,给头部设置着下边距的距离 把内容挤下去显示。
header.style.marginBottom=250+'px';
} else{
//未满足上面条件时,导航栏的定位标签 移除掉 以及 头部的下边距为0
nav.classList.remove('fixed');
header.style.marginBottom=0;
}
})
</script>
</body>
</html>
css的方式完成以上案例
在导航标签加上粘性定位 即可:
position: sticky;
存在兼容性问题 慎用!
主动设置页面的滚动距离示例:
<body>
<button>设置页面滚动距离 200</button>
<header></header>
<nav></nav>
<div>
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
<h1>4</h1>
<h1>5</h1>
<h1>6</h1>
<h1>7</h1>
<h1>8</h1>
<h1>9</h1>
<h1>10</h1>
<h1>11</h1>
<h1>12</h1>
<h1>13</h1>
<h1>14</h1>
<h1>15</h1>
<h1>16</h1>
<h1>17</h1>
<h1>18</h1>
<h1>19</h1>
<h1>20</h1>
<h1>21</h1>
<h1>22</h1>
<h1>23</h1>
<h1>24</h1>
<h1>25</h1>
<h1>26</h1>
<h1>27</h1>
<h1>28</h1>
<h1>29</h1>
<h1>30</h1>
<h1>31</h1>
<h1>32</h1>
<h1>33</h1>
<h1>34</h1>
<h1>35</h1>
<h1>36</h1>
<h1>37</h1>
<h1>38</h1>
<h1>39</h1>
<h1>40</h1>
<h1>41</h1>
<h1>42</h1>
<h1>43</h1>
<h1>44</h1>
<h1>45</h1>
<h1>46</h1>
<h1>47</h1>
<h1>48</h1>
<h1>49</h1>
<h1>50</h1>
<h1>51</h1>
<h1>52</h1>
<h1>53</h1>
<h1>54</h1>
<h1>55</h1>
<h1>56</h1>
<h1>57</h1>
<h1>58</h1>
<h1>59</h1>
<h1>60</h1>
<h1>61</h1>
<h1>62</h1>
<h1>63</h1>
<h1>64</h1>
<h1>65</h1>
<h1>66</h1>
<h1>67</h1>
<h1>68</h1>
<h1>69</h1>
<h1>70</h1>
<h1>71</h1>
<h1>72</h1>
<h1>73</h1>
<h1>74</h1>
<h1>75</h1>
<h1>76</h1>
<h1>77</h1>
<h1>78</h1>
<h1>79</h1>
<h1>80</h1>
<h1>81</h1>
<h1>82</h1>
<h1>83</h1>
<h1>84</h1>
<h1>85</h1>
<h1>86</h1>
<h1>87</h1>
<h1>88</h1>
<h1>89</h1>
<h1>90</h1>
<h1>91</h1>
<h1>92</h1>
<h1>93</h1>
<h1>94</h1>
<h1>95</h1>
<h1>96</h1>
<h1>97</h1>
<h1>98</h1>
<h1>99</h1>
<h1>100</h1>
</div>
<script>
const button = document.querySelector('button');
//给按钮加点击事件
button.addEventListener('click', function () {
// 设置页面的滚动距离
document.documentElement.scrollTop = 200;
});
</script>
</body>