是什么
事件代理,俗地来讲,就是把一个元素响应事件(click、keydown…)的函数委托到另一个元素。前面讲到,事件流的都会经过三个阶段: 捕获阶段 ->目标阶段 ->冒泡阶段,而事件委托就是在冒泡阶段完成.
(上文:事件模型)
捕获阶段 — 事件从window处往目标处传播
目标阶段 — 在目标处触发事件
冒泡阶段 — 事件从目标处往window上传播
e.stopPropagation(); 阻止事件流的传播
e.stopImmediatePropagation(); 阻止事件流的传播 + 阻止同一个容器绑定多个相同的事件
事件委托,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,而不是目标元素。当事件响应到目标元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数
下面举个例子:
比如一个宿舍的同学同时快递到了,一种笨方法就是他们去领取较优方法就是把这件事情委托给宿舍长,让一个人出去拿好所有快递,然后再根据收件人一一分发给每个同学。
在这里,取快递就是一个事件,每个同学指的是需要响应事件的D0M
元素,而出去统一领取快递的宿舍长就是代理的元素。所以真正绑定事件的是这个元素,按照收件人分发快递的过程就是在事件执行中,需要判断当前响应的事件应该匹配到被代理元素中的哪一个或者哪几个
DOM0 VS DOM2
DOM0: onclick…
- 无法人为修改事件在哪个阶段触发
- 同一个容器只能绑定一个相同的事件
DOM2: addEventListener
- 可以人为修改事件在哪个阶段触发
- 同一个容器允许绑定多个相同的事件
应用场景
如果我们有一个列表,列表之中有大量的列表项,我们需要在点击列表项的时候响应一个事件口
"list">
<li>item 1li>
<li>item 2li>
<li>item 3li>
...
- item n
如果给每个列表项都绑定一个函数,那对于内存消耗是非常大的
const lis =document.getElementsByTagName("li")
for(let i=0;i< lis.length; i++){
lis[il.onclick = function(e){
console.log(e.target.innerHTML)
}
}
这时候就可以事件委托,把点击事件绑定在父级元素ul上面,然后执行事件的时候再去匹配目标元素
document.getElementById('list').addEventListener('click', function(e){
var event = e || window.event;
var target =event.target || event.srcElement;
if(target.nodeName.toLocaleLowerCase ==='li'){
console.log('the content is:',target.innerHTML);
}
});
还有一种场景是上述列表项并不多,我们给每个列表项都绑定了事件
但是如果用户能够随时动态的增加或者去除列表项元素,那么在每一次改变的时候都需要重新给新增的元素绑定事件,给即将删去的元素解绑事件
如果用了事件委托就没有这种麻烦了,因为事件是绑定在父层的,和目标元素的增减是没有关系的,执行到目标元素是在真正响应执行事件函数的过程中去匹配的
举个例子:
下面 html结构中,点击 input 可以动态添加元素
"button" name="" id="btn" value="添加"/>
<ul id="ul1">
<li>item 1li>
<li>item 2li>
<li>item 3li>
<li>item 4li>
ul>
使用事件委托
const oBtn=document.getElementById("btn");
const oUl=document.getElementById("ul1");
const num =4;
oUl.onclick =function(ev){
ev = ev || window.event;
const target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == 'li'){
console.log('the content is:',target.innerHTML);
}
}
oBtn.onclick = function(){
num++;
const oLi=document.createElement('li');
oLi.innerHTML = `item ${num}`;
oul.appendchild(oLi);
};
总结
可以看到,使用事件委托,在动态绑定事件的情况下是可以减少很多重复工作的.
适合事件委托的事件有:click
,mousedown
,mouseup
,keydown
,keyup
,keypress
从上面应用场景中,我们就可以看到使用事件委托存在两大优点:
- 减少整个页面所需的内存,提升整体性能
- 动态绑定,减少重复工作
但是使用事件委托也是存在局限性:
focus
、blur
这些事件没有事件冒泡机制,所以无法进行委托绑定事件mousemovemouseout
这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位对性能消耗高,因此也是不适合于事件委托的如果把所有事件都用事件代理,可能会出现事件误判,即本不该被触发的事件被绑定上了事件
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=21157,转载请注明出处。
评论0