一、事件高级内容
1.1、注册事件/绑定事件
1.1.1、概述
1 2
| 1. 给元素添加事件,称为【注册事件】或者【绑定事件】。 2. 注册事件有两种方式:【传统方式】和【方法监听注册方式】。
|
1.1.2、传统注册方式
1 2 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、方法监听注册方式
1 2 3 4 5 6 7 8
| # 语法 eventTarget.addEventListener(type, listener[, useCapture]) 该方法将指定的监听器注册到 eventTarget(目标对象)上,当该对象触发指定的事件时,就会执行事件处理函数。
# 说明 1. type:事件类型字符串,比如 click 、mouseover ,注意这里不要带 on 2. listener:事件处理函数,事件发生时,会调用该监听函数 3. useCapture:可选参数,是一个布尔值,默认是 false。以后再说。
|
1 2 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事件监听方式
1 2 3 4 5 6 7 8 9 10
| # 语法 eventTarget.attachEvent(eventNameWithOn, callback) 该方法将指定的监听器注册到eventTarget(目标对象)上,当该对象触发指定的事件时,指定的回调函数就会被执行 # 说明 1. eventNameWithOn:事件类型字符串,比如 onclick 、onmouseover ,这里要带 on 2. callback: 事件处理函数,当目标触发事件时回调函数被调用 # 注意 1. IE8 及早期版本支持,新版本不支持
|
1 2 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、概述
1 2 3 4 5 6
| # 传统方式 eventTarget.onclick = null; # 方法监听注册方式 1. eventTarget.removeEventListener(type, listener[, useCapture]); 2. eventTarget.detachEvent(eventNameWithOn, callback); // 存在兼容性问题,I8及之前才有效。
|
1.2.2、传统方式
1 2 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、方法监听方式
1 2 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 注册了点击事件,那么这个传播过程是这样的:
1 2
| 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
1 2 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
1 2 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
1 2 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、什么是事件对象
1 2 3 4 5 6 7 8
| eventTarget.onclick = function(event) { }
eventTarget.addEventListener('click', function(event) { })
|
1 2 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;
|
1 2 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
1 2 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
1 2 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
1 2 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
1 2 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
1 2 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
1 2 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
1 2 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、说明
1 2
| 1. 事件冒泡:开始时由最具体的元素接收,然后逐级向上传播到到 DOM 最顶层节点。 2. 事件冒泡本身的特性,会带来的坏处,也会带来的好处,需要我们灵活掌握。
|
3.5.2、案例
1 2 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、需求
1 2 3 4 5
| <ul> <li>高圆圆</li> <li>贾静雯</li> <li>赵敏</li> </ul>
|
点击每个 li 都会弹出对话框弹出每个li里面的内容。
方案:给每个 li 注册点击事件,
问题:麻烦,效率低下。
1 2 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、概述
1 2 3 4 5 6 7 8
| # 事件委托 也称为事件代理, 在 jQuery 里面称为事件委派。 # 事件委托的原理 不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点。 # 案例 给ul注册点击事件,然后利用事件对象的 target 来找到当前点击的 li,因为点击 li,事件会冒泡到 ul 上,ul 有注册事件,就会触发事件监听器。 # 事件委托的作用 我们只操作了一次 DOM ,提高了程序的性能。
|
1 2 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、禁止鼠标右键菜单
1 2 3 4 5 6 7 8 9 10
| <body> <div>我是一段文字</div>
<script> document.addEventListener('contextmenu', function(event) { event.preventDefault(); }) </script> </body>
|
5.3、禁止鼠标选中
1 2 3 4 5 6 7 8 9 10
| <body> <div>我是一段文字</div>
<script> document.addEventListener('selectstart', function(event) { event.preventDefault(); }) </script> </body>
|
5.4、鼠标事件对象
1 2 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、案例
需求:图片一直跟随鼠标移动。
1 2 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
1 2 3 4 5 6 7
| <body> <script> document.addEventListener('keyup', function() { console.log('我弹起了...'); }); </script> </body>
|
1 2 3 4 5 6 7 8
| <body> <script> document.addEventListener('keypress', function() { console.log('keypress'); }); </script> </body>
|
1 2 3 4 5 6 7 8
| <body> <script> document.addEventListener('keydown', function() { console.log('keydown'); }); </script> </body>
|
1 2 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码值
|
1 2 3 4 5 6 7 8 9
| <body> <script> document.addEventListener('keyup', function(event) { if (event.keyCode == 13) { alert('回车用户提交表单'); } }); </script> </body>
|
6.3、案例
需求:当我们按下 s 键, 光标就定位到搜索框
1 2 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>
|