登录
注册
开源
企业版
高校版
搜索
帮助中心
使用条款
关于我们
开源
企业版
高校版
私有云
模力方舟
AI 队友
登录
注册
Gitee 2025年度个人数据报告已发布,快来看看你的成长👉
代码拉取完成,页面将自动刷新
捐赠
捐赠前请先登录
取消
前往登录
扫描微信二维码支付
取消
支付完成
支付提示
将跳转至支付宝完成支付
确定
取消
Watch
不关注
关注所有动态
仅关注版本发行动态
关注但不提醒动态
3
Star
47
Fork
21
DreamCoders
/
CoderGuide
代码
Issues
1169
Pull Requests
0
Wiki
统计
流水线
服务
JavaDoc
PHPDoc
质量分析
Jenkins for Gitee
腾讯云托管
腾讯云 Serverless
悬镜安全
阿里云 SAE
Codeblitz
SBOM
我知道了,不再自动展开
更新失败,请稍后重试!
移除标识
内容风险标识
本任务被
标识为内容中包含有代码安全 Bug 、隐私泄露等敏感信息,仓库外成员不可访问
什么是事件代理,以及它的应用场景有哪些?
待办的
#IAG9PI
陌生人
拥有者
创建于
2024-07-29 16:07
<h2>一、是什么</h2> <p>事件代理,俗地来讲,就是把一个元素响应事件(<code>click</code>、<code>keydown</code>......)的函数委托到另一个元素</p> <p>前面讲到,事件流的都会经过三个阶段: 捕获阶段 -> 目标阶段 -> 冒泡阶段,而事件委托就是在冒泡阶段完成</p> <p>事件委托,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,而不是目标元素</p> <p>当事件响应到目标元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数</p> <p>下面举个例子:</p> <p>比如一个宿舍的同学同时快递到了,一种笨方法就是他们一个个去领取</p> <p>较优方法就是把这件事情委托给宿舍长,让一个人出去拿好所有快递,然后再根据收件人一一分发给每个同学</p> <p>在这里,取快递就是一个事件,每个同学指的是需要响应事件的 <code>DOM</code>元素,而出去统一领取快递的宿舍长就是代理的元素</p> <p>所以真正绑定事件的是这个元素,按照收件人分发快递的过程就是在事件执行中,需要判断当前响应的事件应该匹配到被代理元素中的哪一个或者哪几个</p> <h2>二、应用场景</h2> <p>如果我们有一个列表,列表之中有大量的列表项,我们需要在点击列表项的时候响应一个事件</p> <pre><code class="language-js"><ul id="list"> <li>item 1</li> <li>item 2</li> <li>item 3</li> ...... <li>item n</li> </ul></code></pre> <p>如果给每个列表项一一都绑定一个函数,那对于内存消耗是非常大的</p> <pre><code class="language-js">// 获取目标元素 const lis = document.getElementsByTagName("li") // 循环遍历绑定事件 for (let i = 0; i < lis.length; i++) { lis[i].onclick = function(e){ console.log(e.target.innerHTML) } }</code></pre> <p>这时候就可以事件委托,把点击事件绑定在父级元素<code>ul</code>上面,然后执行事件的时候再去匹配目标元素</p> <pre><code class="language-js">// 给父层元素绑定事件 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); } });</code></pre> <p>还有一种场景是上述列表项并不多,我们给每个列表项都绑定了事件</p> <p>但是如果用户能够随时动态的增加或者去除列表项元素,那么在每一次改变的时候都需要重新给新增的元素绑定事件,给即将删去的元素解绑事件</p> <p>如果用了事件委托就没有这种麻烦了,因为事件是绑定在父层的,和目标元素的增减是没有关系的,执行到目标元素是在真正响应执行事件函数的过程中去匹配的</p> <p>举个例子:</p> <p>下面<code>html</code>结构中,点击<code>input</code>可以动态添加元素</p> <pre><code class="language-html"><input type="button" name="" id="btn" value="添加" /> <ul id="ul1"> <li>item 1</li> <li>item 2</li> <li>item 3</li> <li>item 4</li> </ul></code></pre> <p>使用事件委托</p> <pre><code class="language-js">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); };</code></pre> <p>可以看到,使用事件委托,在动态绑定事件的情况下是可以减少很多重复工作的</p> <h2>三、总结</h2> <p>适合事件委托的事件有:<code>click</code>,<code>mousedown</code>,<code>mouseup</code>,<code>keydown</code>,<code>keyup</code>,<code>keypress</code></p> <p>从上面应用场景中,我们就可以看到使用事件委托存在两大优点:</p> <ul> <li>减少整个页面所需的内存,提升整体性能</li> <li>动态绑定,减少重复工作</li> </ul> <p>但是使用事件委托也是存在局限性:</p> <ul> <li> <p><code>focus</code>、<code>blur</code>这些事件没有事件冒泡机制,所以无法进行委托绑定事件</p> </li> <li> <p><code>mousemove</code>、<code>mouseout</code>这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位,对性能消耗高,因此也是不适合于事件委托的</p> </li> </ul> <p>如果把所有事件都用事件代理,可能会出现事件误判,即本不该被触发的事件被绑定上了事件</p>
<h2>一、是什么</h2> <p>事件代理,俗地来讲,就是把一个元素响应事件(<code>click</code>、<code>keydown</code>......)的函数委托到另一个元素</p> <p>前面讲到,事件流的都会经过三个阶段: 捕获阶段 -> 目标阶段 -> 冒泡阶段,而事件委托就是在冒泡阶段完成</p> <p>事件委托,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,而不是目标元素</p> <p>当事件响应到目标元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数</p> <p>下面举个例子:</p> <p>比如一个宿舍的同学同时快递到了,一种笨方法就是他们一个个去领取</p> <p>较优方法就是把这件事情委托给宿舍长,让一个人出去拿好所有快递,然后再根据收件人一一分发给每个同学</p> <p>在这里,取快递就是一个事件,每个同学指的是需要响应事件的 <code>DOM</code>元素,而出去统一领取快递的宿舍长就是代理的元素</p> <p>所以真正绑定事件的是这个元素,按照收件人分发快递的过程就是在事件执行中,需要判断当前响应的事件应该匹配到被代理元素中的哪一个或者哪几个</p> <h2>二、应用场景</h2> <p>如果我们有一个列表,列表之中有大量的列表项,我们需要在点击列表项的时候响应一个事件</p> <pre><code class="language-js"><ul id="list"> <li>item 1</li> <li>item 2</li> <li>item 3</li> ...... <li>item n</li> </ul></code></pre> <p>如果给每个列表项一一都绑定一个函数,那对于内存消耗是非常大的</p> <pre><code class="language-js">// 获取目标元素 const lis = document.getElementsByTagName("li") // 循环遍历绑定事件 for (let i = 0; i < lis.length; i++) { lis[i].onclick = function(e){ console.log(e.target.innerHTML) } }</code></pre> <p>这时候就可以事件委托,把点击事件绑定在父级元素<code>ul</code>上面,然后执行事件的时候再去匹配目标元素</p> <pre><code class="language-js">// 给父层元素绑定事件 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); } });</code></pre> <p>还有一种场景是上述列表项并不多,我们给每个列表项都绑定了事件</p> <p>但是如果用户能够随时动态的增加或者去除列表项元素,那么在每一次改变的时候都需要重新给新增的元素绑定事件,给即将删去的元素解绑事件</p> <p>如果用了事件委托就没有这种麻烦了,因为事件是绑定在父层的,和目标元素的增减是没有关系的,执行到目标元素是在真正响应执行事件函数的过程中去匹配的</p> <p>举个例子:</p> <p>下面<code>html</code>结构中,点击<code>input</code>可以动态添加元素</p> <pre><code class="language-html"><input type="button" name="" id="btn" value="添加" /> <ul id="ul1"> <li>item 1</li> <li>item 2</li> <li>item 3</li> <li>item 4</li> </ul></code></pre> <p>使用事件委托</p> <pre><code class="language-js">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); };</code></pre> <p>可以看到,使用事件委托,在动态绑定事件的情况下是可以减少很多重复工作的</p> <h2>三、总结</h2> <p>适合事件委托的事件有:<code>click</code>,<code>mousedown</code>,<code>mouseup</code>,<code>keydown</code>,<code>keyup</code>,<code>keypress</code></p> <p>从上面应用场景中,我们就可以看到使用事件委托存在两大优点:</p> <ul> <li>减少整个页面所需的内存,提升整体性能</li> <li>动态绑定,减少重复工作</li> </ul> <p>但是使用事件委托也是存在局限性:</p> <ul> <li> <p><code>focus</code>、<code>blur</code>这些事件没有事件冒泡机制,所以无法进行委托绑定事件</p> </li> <li> <p><code>mousemove</code>、<code>mouseout</code>这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位,对性能消耗高,因此也是不适合于事件委托的</p> </li> </ul> <p>如果把所有事件都用事件代理,可能会出现事件误判,即本不该被触发的事件被绑定上了事件</p>
评论 (
0
)
登录
后才可以发表评论
状态
待办的
待办的
进行中
已完成
已关闭
负责人
未设置
标签
Html/JS/CSS
未设置
标签管理
里程碑
未关联里程碑
未关联里程碑
Pull Requests
未关联
未关联
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
未关联
未关联
master
开始日期   -   截止日期
-
置顶选项
不置顶
置顶等级:高
置顶等级:中
置顶等级:低
优先级
不指定
严重
主要
次要
不重要
参与者(1)
1
https://gitee.com/DreamCoders/CoderGuide.git
git@gitee.com:DreamCoders/CoderGuide.git
DreamCoders
CoderGuide
CoderGuide
点此查找更多帮助
搜索帮助
Git 命令在线学习
如何在 Gitee 导入 GitHub 仓库
Git 仓库基础操作
企业版和社区版功能对比
SSH 公钥设置
如何处理代码冲突
仓库体积过大,如何减小?
如何找回被删除的仓库数据
Gitee 产品配额说明
GitHub仓库快速导入Gitee及同步更新
什么是 Release(发行版)
将 PHP 项目自动发布到 packagist.org
评论
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册