乐趣区

js事件委托总结

补充一直没写的总结???? 当简单回顾咯
DOM 事件流
DOM 事件流包括三个阶段:事件捕获阶段,处于目标阶段与事件冒泡阶段

即比如点击 td 元素时,由外至内层会经历捕获阶段,目标阶段,冒泡阶段三个阶段,相应地会触发路径元素上的事件 此外,addEventListener(type, listener[, useCapture]) 函数默认设置在冒泡阶段,路径元素的事件才会触发,此参数为可选值,默认值为 false,示例代码一并标出 示例代码:
<div id=”grandFather” style=”width: 700px;height: 700px; background-color: red”>
<p>grandFather</p>
<div id=”father1″ style=”width: 300px; height: 300px; background-color: pink”>
<p>father1</p>
<div id=”son1″ style=”width: 100px; height: 100px; background-color: yellow”>
<p>son1</p>
</div>
</div>
<div id=”father2″ style=”width: 300px;height: 300px; background-color: green”>
<p>father2</p>
</div>
</div>
<script type=”text/javascript”>
let grandFather = document.getElementById(‘grandFather’),
father1 = document.getElementById(‘father1’),
son1 = document.getElementById(‘son1’),
father2 = document.getElementById(‘father2’);

grandFather.addEventListener(‘click’, function(event){console.log(‘I am grandFather’)},true);
father1.addEventListener(‘click’, function(event){console.log(‘I am father1’)},false);
son1.addEventListener(‘click’, function(event){console.log(‘I am son1’)},false);
father2.addEventListener(‘click’, function(event){console.log(‘I am father2’)},false);
</script>
点击 son1 div 时,会冒泡触发 father1 与 grandFather 事件

若将 grandFather 的 use capture 参数改为 true,则会相应改变执行顺序
grandFather.addEventListener(‘click’, function(event){console.log(‘I am grandFather’)},true);

以上是事件流的简单总结,下面事件委托是对事件冒泡的应用
事件委托
如果在需要有多个 DOM 事件需要监听的情况下(比如几百条微博点击事件注册),给每一个 DOM 都绑定监听函数,对性能会有极大的影响,因此,有一解决方案为事件委托。事件委托利用了事件冒泡与 event.target
event.currentTarget 与 event.target
currentTarget:表示此事件绑定的元素 target:通俗理解为表示触发一系列事件的源头 我们再次修改 grandFather 的监听函数
grandFather.addEventListener(‘click’, function(event){
console.log(‘I am grandFather!!!’)
console.log(‘currentTarget:’);
console.log(event.currentTarget);
console.log(‘target:’);
console.log(event.target);},false); // 这里已改回 false
再次点击 son1,进入 grandFather 的监听函数后显示如下

事件委托具体步骤
了解冒泡与 target 后,不难可以想到若是在几百个 dom 监听之中,只需把监听函数绑定在父容器上即可,这里依旧拿这个简单的例子修改,我们要做的是点击某个 div 便显示打印 ’I am xxx’ 首先,给 div 都绑定自定义的 data-name 属性
<!– 没有给 p 元素设置 data-name,点击 p 元素时会显示 data-name 为 null –>
<div id=”grandFather” data-name=”grandFather” style=”width: 700px;height: 700px; background-color: red”>
<p>grandFather</p>
<div id=”father1″ data-name=”father1″ style=”width: 300px; height: 300px; background-color: pink”>
<p>father1</p>
<div id=”son1″ data-name=”son1″ style=”width: 100px; height: 100px; background-color: yellow”>
<p>son1</p>
</div>
</div>
<div id=”father2″ data-name=”father2″ style=”width: 300px;height: 300px; background-color: green”>
<p>father2</p>
</div>
</div>
接着改写 grandFather 的监听函数
grandFather.addEventListener(‘click’, function(event){
console.log(‘I am ‘ + event.target.getAttribute(‘data-name’));
},false);
// 这些可以注释掉了!
// father1.addEventListener(‘click’, function(event){console.log(‘I am father1’)},false);
// son1.addEventListener(‘click’, function(event){console.log(‘I am son1’)},false);
// father2.addEventListener(‘click’, function(event){console.log(‘I am father2’)},false);
这样子就是一个简单的委托,更多的应用可以结合 switch 等等
参考资料
《Javascript 高级程序设计》MDN:Event.target MDN:event.currentTarget w3:DOM Event Architecture

退出移动版