事件委托(事件代理)
將原本需要綁定在子元素上的事件監聽器委托在父元素上,讓父元素充當事件監聽的職務。
事件委托是一種利用事件冒泡的特性,在父節點上響應事件,而不是在子節點上響應事件的技術。它能夠改善性能,因為只需要在父元素上設置一次事件監聽器,就可以管理同一類型的所有子元素的事件。
事件委托利用了事件冒泡的原理,即事件從最深的節點開始,逐步向上傳播。在事件冒泡過程中,父元素會捕獲到子元素的事件,并進行分析。通過查看event對象的屬性,可以確定是哪個子元素的事件,從而執行相應的處理邏輯。
使用事件委托能夠避免對每個子元素單獨設置事件監聽器,降低了與DOM交互的次數,提高了頁面的整體運行性能。同時,事件委托也具有更高的靈活性和可維護性,不需要操作大量的DOM元素。
在Vue中,可以利用v-on
指令或@
符號來綁定事件監聽器,并在父元素上設置事件委托。例如,可以在父元素上設置一個click事件監聽器,然后在子元素上綁定一個click事件,通過事件委托實現父元素對子元素事件的響應。
優點:
節省內存(dom與js的關聯),減少事件的注冊
增加子元素也無需再注冊事件
缺點:
獲取綁定的節點數據會相對麻煩一點
在日常開發中,很經常我們會遇到個問題,就是在長列表數據較多的時候,而又需要對子元素注冊一些事件(如onClick),就會造成比較大的內存開支,很耗費性能,也可能會造成頁面卡頓等等;
所以可以通過在父元素上添加@click監聽,而不是在子元素上注冊事件;
如果數據量比較少,就可忽略不計;
html代碼:
<div id="app"><div id="event-agent" @click="eventAgent"><p v-for="(item, index) in list" :key="index" :data-name="item.name" :data-index="index">{{item.name}}</p></div>
</div>
獲取節點參數 (data-index、data-name),則在 $event.target.dataset { index: 'xxx', name: 'xxx' } 中取值
?js代碼
data() {return { list: [{ id: 1, name: 'kmj1'},{ id: 2, name: 'kmj2'},{ id: 3, name: 'kmj3'},{ id: 4, name: 'kmj4'}] }
},
methods: { // 事件委托eventAgent(e) {const target = e.target; console.log(target )// 注意 e.target.nodeName 的元素名是大寫的if (target && target.nodeName === "P") {const dataset = target .dataset;console.log('$event.target.dataset : ' dataset ); // $event.target.dataset : { name: 'xxx', index: 'xxx' }}}
}
原生的寫法其實也差不多:
document.getElementById( "event-agent").onclick = function(event){ // 兼容Ie的寫法event = event || window.event;var target = event.target || event.srcElement; // 注意 e.target.nodeName 的元素名是大寫的if (target && target.nodeName === "P") {const dataset = target .dataset;console.log('$event.target.dataset : ' dataset ); // $event.target.dataset : { name: 'xxx', index: 'xxx' }}
}; // 也可以用這種方式,其實都差不多的:
// 冒泡階段處理程序
document.getElementById( "event-agent").addEventListener( "click", (e) => {}, false);
// 捕獲階段處理程序
document.getElementById( "event-agent").addEventListener( "click", (e) => {}, true);