一、事件高级内容
1.1、注册事件/绑定事件
1.1.1、概述
| 12
 
 | 1. 给元素添加事件,称为【注册事件】或者【绑定事件】。2. 注册事件有两种方式:【传统方式】和【方法监听注册方式】。
 
 | 

1.1.2、传统注册方式
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | <body><button>点击</button>
 <script>
 
 var btnObj = document.querySelector("button");
 
 
 btnObj.onclick = function() {
 alert('HelloWorld');
 }
 
 btnObj.onclick = function() {
 alert('JavaScript');
 }
 
 
 </script>
 </body>
 
 | 
1.1.3、方法监听注册方式
| 12
 3
 4
 5
 6
 7
 8
 
 | # 语法eventTarget.addEventListener(type, listener[, useCapture])
 该方法将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
 
 # 说明
 1. type:事件类型字符串,比如 click 、mouseover ,注意这里不要带 on
 2. listener:事件处理函数,事件发生时,会调用该监听函数
 3. useCapture:可选参数,是一个布尔值,默认是 false。以后再说。
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | <body><button>点击</button>
 <script>
 
 var btnObj = document.querySelector("button");
 
 
 btnObj.addEventListener('click', function() {
 alert('HelloWorld');
 });
 
 btnObj.addEventListener('click', function() {
 alert('JavaScript');
 })
 
 
 </script>
 </body>
 
 | 
1.1.4、attachEvent事件监听方式
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | # 语法eventTarget.attachEvent(eventNameWithOn, callback)
 该方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,指定的回调函数就会被执行
 
 # 说明
 1. eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on
 2. callback: 事件处理函数,当目标触发事件时回调函数被调用
 
 # 注意
 1. IE8 及早期版本支持,新版本不支持
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | <body><button>点击</button>
 <script>
 
 var btnObj = document.querySelector("button");
 
 
 btnObj.attachEvent("onclick", function() {
 alert('HelloWorld');
 });
 
 btnObj.attachEvent("onclick", function() {
 alert('JavaScript');
 });
 
 
 </script>
 </body>
 
 | 

1.2、删除事件/解绑事件
1.2.1、概述
| 12
 3
 4
 5
 6
 
 | # 传统方式eventTarget.onclick = null;
 
 # 方法监听注册方式
 1. eventTarget.removeEventListener(type, listener[, useCapture]);
 2. eventTarget.detachEvent(eventNameWithOn, callback); // 存在兼容性问题,I8及之前才有效。
 
 | 
1.2.2、传统方式
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | <body><button id="btn1">传统方式绑定事件</button>
 <button id="btn2">传统方式解绑事件</button>
 <script>
 
 var btn1Obj = document.querySelector("#btn1");
 btn1Obj.onclick = function() {
 alert('HelloWorld');
 }
 
 
 var btn2Obj = document.querySelector("#btn2");
 btn2Obj.onclick = function() {
 btn1Obj.onclick = null;
 }
 </script>
 </body>
 
 | 
1.2.3、方法监听方式
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | <body><button id="btn1">方法监听方式绑定事件</button>
 <button id="btn2">方法监听方式解绑事件</button>
 <script>
 
 var btn1Obj = document.querySelector("#btn1");
 btn1Obj.addEventListener('click', fn1);
 
 function fn1() {
 alert('JavaScript');
 }
 
 
 var btn2Obj = document.querySelector("#btn2");
 btn2Obj.onclick = function() {
 btn1Obj.removeEventListener('click', fn1);
 }
 </script>
 </body>
 
 | 
二、DOM事件流
2.1、概述
        事件流描述的是从页面中接收事件的顺序。
        事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即 DOM 事件流。
        比如我们给一个div 注册了点击事件,那么这个传播过程是这样的:

| 12
 
 | 1. 事件冒泡: IE 最早提出,事件开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点的过程。2. 事件捕获: 网景最早提出,由 DOM 最顶层节点开始,然后逐级向下传播到到最具体的元素接收的过程。
 
 | 
2.2、通俗理解
        我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具
体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点( 最具体元素)之后漂浮到水面上,这个过
程相当于事件冒泡。

2.3、注意点
- JS 代码中只能执行捕获或者冒泡其中的一个阶段。
- onclick 和 attachEvent 只能得到冒泡阶段。
- addEventListener(type, listener[, useCapture])第三个参数如果是 true,表示在事件捕获阶段调用事件处理程序;如果是 false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序。
- ==实际开发中我们很少使用事件捕获,我们更关注事件冒泡。==
- ==有些事件是没有冒泡的,比如 onblur、onfocus、onmouseenter、onmouseleave==
- 事件冒泡有时候会带来麻烦,有时候又会帮助很巧妙的做某些事件,我们后面讲解。
2.4、案例1
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 
 | <head><style>
 #div1 {
 width: 300px;
 height: 300px;
 background-color: red;
 }
 
 #div2 {
 width: 200px;
 height: 200px;
 background-color: blue;
 }
 
 #div3 {
 width: 100px;
 height: 100px;
 background-color: skyblue;
 }
 </style>
 </head>
 <body>
 <div id="div1">
 <div id="div2">
 <div id="div3"></div>
 </div>
 </div>
 <script>
 
 
 
 var div1 = document.querySelector("#div1");
 div1.onclick = function() {
 alert('div1');
 }
 
 
 var div2 = document.querySelector("#div2");
 div2.onclick = function() {
 alert('div2');
 }
 
 
 var div3 = document.querySelector("#div3");
 div3.onclick = function() {
 alert('div3');
 }
 </script>
 </body>
 
 | 
2.5、案例2
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 
 | <body><div id="div1">
 <div id="div2">
 <div id="div3"></div>
 </div>
 </div>
 <script>
 
 
 
 var div1 = document.querySelector("#div1");
 div1.addEventListener('click', function() {
 alert("div1");
 });
 
 
 var div2 = document.querySelector("#div2");
 div2.addEventListener('click', function() {
 alert("div2");
 });
 
 
 var div3 = document.querySelector("#div3");
 div3.addEventListener('click', function() {
 alert("div3");
 });
 </script>
 </body>
 
 | 
2.6、案例3
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 
 | <body><div id="div1">
 <div id="div2">
 <div id="div3"></div>
 </div>
 </div>
 <script>
 
 
 
 var div1 = document.querySelector("#div1");
 div1.addEventListener('click', function() {
 alert("div1");
 }, true);
 
 
 var div2 = document.querySelector("#div2");
 div2.addEventListener('click', function() {
 alert("div2");
 }, true);
 
 
 var div3 = document.querySelector("#div3");
 div3.addEventListener('click', function() {
 alert("div3");
 }, true);
 </script>
 </body>
 
 | 
三、事件对象
3.1、什么是事件对象
| 12
 3
 4
 5
 6
 7
 8
 
 | eventTarget.onclick = function(event) {
 }
 
 eventTarget.addEventListener('click', function(event) {
 
 })
 
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 
 | # 官方解释event 对象代表事件的状态,比如键盘按键的状态、鼠标的位置、鼠标按钮的状态。
 
 # 通俗理解
 事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象event,它有很多属性和方法。
 例如:
 1. 谁绑定了这个事件。
 2. 鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置。
 3. 键盘触发事件的话,会得到键盘的相关信息,如按了哪个键。
 
 # 注意点
 事件对象本身的获取存在兼容问题:
 1. 标准浏览器中是浏览器给方法传递的参数,只需要定义形参 event 就可以获取到。
 2. 在 IE6~8 中,浏览器不会给方法传递参数,如果需要的话,需要到 window.event 中获取查找。
 
 解决兼容性问题:
 event = event || window.event;
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 
 | <body><div>HelloWorld</div>
 <script>
 
 var divObj = document.querySelector('div');
 
 
 divObj.onclick = function(event) {
 event = event || window.event;
 console.log(event);
 }
 
 
 divObj.addEventListener('click', function(event) {
 console.log(event);
 });
 </script>
 </body>
 
 | 
3.2、e.target 和 this 的区别
3.2.1、案例1
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | <body><div>HelloWorld</div>
 <script>
 
 
 
 var divObj = document.querySelector("div");
 
 divObj.addEventListener('click', function(event) {
 console.log(this);
 console.log(event.target);
 })
 
 
 </script>
 </body>
 
 | 
3.2.2、案例2
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 
 | <body><ul>
 <li>高圆圆</li>
 <li>贾静雯</li>
 <li>赵敏</li>
 </ul>
 <script>
 
 
 
 var ulObj = document.querySelector("ul");
 
 
 ulObj.addEventListener('click', function(event) {
 console.log(this);
 console.log(event.target);
 })
 
 
 
 
 
 
 
 
 </script>
 </body>
 
 | 
3.2.3、案例3
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | <body><ul>
 <li>高圆圆</li>
 <li>贾静雯</li>
 <li>赵敏</li>
 </ul>
 <script>
 
 
 
 var ulObj = document.querySelector("ul");
 
 
 ulObj.addEventListener('click', function(event) {
 console.log(this);
 console.log(event.currentTarget);
 })
 
 
 
 </script>
 </body>
 
 | 
3.3、事件对象的常见属性和方法

3.4、阻止事件默认行为
3.4.1、说明
| 1
 | # 所谓的阻止事件默认行为,比如说让超链接不跳转,让提交按钮本来要提交表单的事件不发生。
 | 
3.4.2、案例1
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | <body><a href="https://www.baidu.com">跳转到百度</a>
 <script>
 
 
 var aObj = document.querySelector("a");
 
 
 aObj.addEventListener('click', function(event) {
 alert("阻止超链接跳转哦");
 event.preventDefault();
 })
 </script>
 </body>
 
 | 
3.4.3、案例2
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | <body><a href="https://www.baidu.com">跳转到百度</a>
 <script>
 
 
 var aObj = document.querySelector("a");
 
 
 aObj.onclick = function(event) {
 alert("阻止超链接的默认行为哦");
 event.preventDefault();
 }
 </script>
 </body>
 
 | 
3.4.3、案例3
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | <body><a href="https://www.baidu.com">跳转到百度</a>
 <script>
 
 
 var aObj = document.querySelector("a");
 
 
 aObj.onclick = function(event) {
 alert("阻止超链接的默认行为哦");
 event.returnValue;
 }
 </script>
 </body>
 
 | 
3.4.4、案例4
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | <body><a href="https://www.baidu.com">跳转到百度</a>
 <script>
 
 
 var aObj = document.querySelector("a");
 
 
 aObj.onclick = function(event) {
 alert("阻止超链接的默认行为哦");
 return false;
 }
 </script>
 </body>
 
 | 
3.5、阻止事件冒泡
3.5.1、说明
| 12
 
 | 1. 事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点。2. 事件冒泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握。
 
 | 
3.5.2、案例
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 
 | <head><style>
 #div1 {
 width: 300px;
 height: 300px;
 background-color: red;
 }
 
 #div2 {
 width: 200px;
 height: 200px;
 background-color: blue;
 }
 
 #div3 {
 width: 100px;
 height: 100px;
 background-color: skyblue;
 }
 </style>
 </head>
 <body>
 <div id="div1">
 <div id="div2">
 <div id="div3"></div>
 </div>
 </div>
 <script>
 
 var div1 = document.querySelector("#div1");
 div1.addEventListener('click', function() {
 alert("div1");
 });
 
 
 var div2 = document.querySelector("#div2");
 div2.addEventListener('click', function() {
 alert("div2");
 });
 
 
 var div3 = document.querySelector("#div3");
 div3.addEventListener('click', function(event) {
 alert("div3");
 event.stopPropagation();
 
 });
 </script>
 </body>
 
 | 
四、事件委托/代理/委派
4.1、理解
        事件冒泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握。生活中有如下场景:
咱们班有100个学生, 快递员有100个快递, 如果一个个的送花费时间较长。同时每个学生领取的时候,也需
要排队领取,也花费时间较长,何如办呢?
        解决方案: 快递员把100个快递,委托给班主任,班主任把这些快递放到办公室,同学们下课自行领取即可。
        优势: 快递员省事,委托给班主任就可以走了。 同学们领取也方便,因为相信班主任。
4.2、需求
| 12
 3
 4
 5
 
 | <ul><li>高圆圆</li>
 <li>贾静雯</li>
 <li>赵敏</li>
 </ul>
 
 | 
        点击每个 li 都会弹出对话框弹出每个li里面的内容。
        方案:给每个 li 注册点击事件,
        问题:麻烦,效率低下。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | <body><ul>
 <li>高圆圆</li>
 <li>贾静雯</li>
 <li>赵敏</li>
 </ul>
 
 <script>
 var liObjs = document.querySelectorAll("li");
 for (var i = 0; i < liObjs.length; i++) {
 liObjs[i].onclick = function() {
 alert(this.innerHTML);
 }
 }
 </script>
 </body>
 
 | 
4.3、概述
| 12
 3
 4
 5
 6
 7
 8
 
 | # 事件委托也称为事件代理, 在 jQuery 里面称为事件委派。
 # 事件委托的原理
 不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。
 # 案例
 给ul注册点击事件,然后利用事件对象的 target 来找到当前点击的 li,因为点击 li,事件会冒泡到 ul 上,ul 有注册事件,就会触发事件监听器。
 # 事件委托的作用
 我们只操作了一次 DOM ,提高了程序的性能。
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | <body><ul>
 <li>高圆圆</li>
 <li>贾静雯</li>
 <li>赵敏</li>
 </ul>
 
 <script>
 
 var ulObj = document.querySelector("ul");
 
 ulObj.addEventListener("click", function(event) {
 alert(event.target.innerHTML);
 });
 </script>
 </body>
 
 | 
五、鼠标事件
5.1、常用的鼠标事件

5.2、禁止鼠标右键菜单
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | <body><div>我是一段文字</div>
 
 <script>
 
 document.addEventListener('contextmenu', function(event) {
 event.preventDefault();
 })
 </script>
 </body>
 
 | 
5.3、禁止鼠标选中
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | <body><div>我是一段文字</div>
 
 <script>
 
 document.addEventListener('selectstart', function(event) {
 event.preventDefault();
 })
 </script>
 </body>
 
 | 
5.4、鼠标事件对象

| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | <head><style>
 body {
 height: 3000px;
 }
 </style>
 </head>
 <body>
 <script>
 
 document.addEventListener('click', function(event) {
 
 console.log(event.clientX);
 console.log(event.clientY);
 console.log('---------------------');
 
 
 console.log(event.pageX);
 console.log(event.pageY);
 console.log('---------------------');
 })
 </script>
 </body>
 
 | 
5.5、案例
        需求:图片一直跟随鼠标移动。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | <head><style>
 img {
 position: absolute;
 top: 2px;
 }
 </style>
 </head>
 <body>
 <img src="img/angel.gif" alt="">
 <script>
 
 var imgObj = document.querySelector("img");
 
 document.addEventListener('mousemove', function(event) {
 
 var x = event.pageX;
 var y = event.pageY;
 
 
 imgObj.style.left = x - 50 + 'px';
 imgObj.style.top = y - 40 + 'px';
 });
 </script>
 </body>
 
 | 
六、键盘事件
6.1、常用的键盘事件

注意:
- 如果使用addEventListener不需要加on
- onkeypress 和前面2个的区别是,它不识别功能键,比如左右箭头,shift 等
- 三个事件的执行顺序是: keydown — keypress —- keyup
| 12
 3
 4
 5
 6
 7
 
 | <body><script>
 document.addEventListener('keyup', function() {
 console.log('我弹起了...');
 });
 </script>
 </body>
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 
 | <body><script>
 
 document.addEventListener('keypress', function() {
 console.log('keypress');
 });
 </script>
 </body>
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 
 | <body><script>
 
 document.addEventListener('keydown', function() {
 console.log('keydown');
 });
 </script>
 </body>
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | <body>
 <script>
 document.addEventListener('keydown', function() {
 console.log('keydown');
 });
 document.addEventListener('keyup', function() {
 console.log('keyup');
 });
 document.addEventListener('keypress', function() {
 console.log('keypress');
 });
 
 
 </script>
 </body>
 
 | 
6.2、键盘事件对象属性

| 1
 | # 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | <body><script>
 document.addEventListener('keyup', function(event) {
 if (event.keyCode == 13) {
 alert('回车用户提交表单');
 }
 });
 </script>
 </body>
 
 | 
6.3、案例
        需求:当我们按下 s 键, 光标就定位到搜索框
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | <body>搜索: <input type="text" placeholder="请输入你要搜索的内容">
 <script>
 
 
 
 var inputObj = document.querySelector('input');
 
 
 document.addEventListener('keyup', function(event) {
 if (event.keyCode == 83) {
 inputObj.focus();
 }
 });
 </script>
 </body>
 
 |