元旦過後,新年第一篇。
初衷:很多的面試都會涉及到事件委託,前後後也看過好多博文,寫的都很不錯,寫的各有千秋,自己思前想後,為了以後自己的查看,也同時為現在找工作的前端小夥伴提供一個看似更全方位的解讀事件委託的地方來認識了解他的原理,本篇文章匯總了兩個版本的事件委託:javascript、jquery;
利用事件冒泡,只指定一個事件處理程序,就可以管理某一類型的所有事件。
在js中加入到頁面上的事件處理程序的數量直接影響到網頁的運作效能。因為每個事件處理函數都是一個對象,是對象就會佔用內存,而內存中對象越多,導致的結果就是性能越差;而訪問dom的次數越多,就會引起結構的重繪或者重排的次數也隨之增多,會延遲整個頁面的互動就緒時間;
對於在頁面進行處理過後新增的dom元素,運用事件委託可以為新增的dom元素一併增減事件處理程序;
<p> </p><p>第一个p</p> <p>第二个p</p> <p>第三个p</p> <p> </p><p>这是子集菜单</p> <p>我是子集的p </p><p>我是子集的p</p> <button>点击加一</button>
在js中不用事件委託的情況:取得頁面中所有的p標籤然後用for迴圈遍歷給每一個元素增加事件處理函數
let nodes = document.getElementById("nodes"); let ps = document.getElementsByTagName("p"); console.log(ps); let btn = document.getElementsByTagName("button")[0]; let inner = 33; btn.onclick = function() { inner++; let p = document.createElement("p"); p.innerHTML = inner + "新增的p标签啊"; nodes.appendChild(p); console.log(ps); }; for (let i= 0;i<ps.length><p>這時候在瀏覽器中運行之後進行測試,發現如圖一所示的結果;</p><p><img src="https://img.php.cn/upload/image/376/157/896/1593567746839219.png" title="1593567746839219.png" alt="javascript事件委託和jquery事件委託"></p><p>那麼js不用事件委託怎麼給新增加的標籤添加事件處理函數呢?解決方案如下:</p><pre class="brush:php;toolbar:false">let nodes = document.getElementById("nodes"); let ps = document.getElementsByTagName("p"); console.log(ps); let btn = document.getElementsByTagName("button")[0]; let inner = 33; btn.onclick = function () { inner++; let p = document.createElement("p"); p.innerHTML = inner + "新增的p标签啊"; nodes.appendChild(p); addEvent();//将新dom元素增加到页面后再执行循环函数 console.log(ps); }; function addEvent() { for (let i = 0; i <p>這時候瀏覽器中運行如圖二所示:</p><p><img src="https://img.php.cn/upload/image/129/624/157/1593567770605067.png" title="1593567770605067.png" alt="javascript事件委託和jquery事件委託"></p><p>#這時候雖然解決了為新增dom元素增加事件處理函數的問題,但是仔細考慮他的性能卻是比之前都有所下降,究其原因就是又增加了一個事件處理函數(對象),又一次佔用了內存;所以,這個時候就會用到事件委託,這時候事件委託的優勢也有所體現:</p><pre class="brush:php;toolbar:false">let nodes = document.getElementById("nodes"); let ps = document.getElementsByTagName("p"); console.log(ps); let btn = document.getElementsByTagName("button")[0]; let inner = 33; btn.onclick = function () { inner++; let p = document.createElement("p"); p.innerHTML = inner + "新增的p标签啊"; nodes.appendChild(p); console.log(ps); }; //事件委托,为nodes指定一个事件处理函数,处理nodes下为p标签的所有元素的cilck事件 nodes.onclick= function(e){ let ev = e || window.event let target = ev.target || ev.srcElement //srcElement IE浏览器 //这里要判被处理元素节点的名字,也可以增加相应的判断条件 target.nodeName.toLowerCase() == 'p'||target.nodeName.toLowerCase() == 'span',但是要注意不要使用父级元素的名称,因为再点击子元素之间的空气的时候,由于事件冒泡他会给父级元素也增加相应的事件处理函数;因为返回的节点名称一般都是大写,所以这时要用toLowerCase()处理一下; if(target.nodeName.toLowerCase() == 'p'){ target.style.background = 'green' } }
這時候瀏覽器中運行的結果如圖三所示:
相較於js事件委託,jquery事件委託的優勢:執行事件委託的時候只有子元素會觸發事件函數,而代為執行的父元素不會觸發事件函數,因此不用去判斷元素節點的名稱;(注意這裡的事件委託用的方法on,如果用bind方法父元素會觸發事件函數)
這裡nodes節點下所有標籤為p的子節點都被賦予事件處理函數;這裡的子節點還可以是多個類似' p,span',需要注意這裡面也不可以寫同nodes一樣的標籤,否則點擊元素之間的間隔會給nodes下的p賦予事件處理函數;如例二:
例一:
let inner = 33; //这里nodes节点下所有标签为p的子节点都被赋予事件处理函数;这里的子节点还可以是多个类似' p,span',需要注意这里面也不可以写同nodes一样的标签,否则点击元素之间的间隔会给nodes下的p赋予事件处理函数 $('#nodes').on('click','p',function(e){ let target = $(e.target) target.css('backgroundColor','red') }) $('button').click(()=>{ inner++; $('#nodes').append($('<p>我是新增加的p标签'+inner+'</p>')) })
瀏覽器運行的效果如圖四所示:
範例二:
<p> </p><p>第一个p</p> <p>第二个p</p> <p>第三个p</p> <span>span</span> <p> </p><p>这是子集菜单</p> <p>我是子集的p </p><p>我是子集的p</p> <button>点击加一</button> <script> let inner =33; $('#nodes').on('click','p,p,span',function(e){ let target = $(e.target) target.css('backgroundColor','red') }) $('button').click(()=>{ inner++; $('#nodes').append($('<p>我是新增加的p标签'+inner+'')) }) </script>
瀏覽器運作效果如圖五所示:
<p> <input> <input> </p> <p> </p> <script></script> <script> let events = document.getElementById('events'); let content = document.getElementById('content'); events.onclick=function(e){ let ev = e || window.event; let target = ev.target || ev.srcElement; if(target.nodeName.toLowerCase()=='input'){ switch(target.id){ case 'addHandle': return addEvent(); break case 'deleteHandle': return deleteEvent(); break } } } function addEvent(){ let add = document.createElement('p') add.innerHTML = '这是增加按钮' content.appendChild(add) } function deleteEvent(){ let del = document.createElement('p') del.innerHTML = '这是删除按钮' content.appendChild(del) } </script>
瀏覽器中的效果如圖六所示:
$('#events').on('click','input',(e)=>{ let target = $(e.target); switch(target[0].id){ case 'addHandle': return addEvent(); break case 'deleteHandle': return deleteEvent(); break } }) function addEvent(){ $('#content').append($('<p>这是增加按钮</p>')) } function deleteEvent(){ $('#content').append($('<p>这是删除按钮</p>')) }
瀏覽器中的效果如圖七所示:
本文如有不實之處,也望大神指點一二,歡迎討論!
推薦教學:《JS教學》
以上是javascript事件委託和jquery事件委託的詳細內容。更多資訊請關注PHP中文網其他相關文章!