標(biāo)簽(空格分隔): 事件委托 冒泡 性能優(yōu)化
序:
開(kāi)啟本文前巢墅,首先有幾點(diǎn)要說(shuō)明一下侦铜。
問(wèn)題
1:添加到文檔上的事件處理程序越多院塞,頁(yè)面整體運(yùn)行性能越低。
2:每個(gè)函數(shù)都是對(duì)象戏溺,都要占內(nèi)存渣蜗,內(nèi)存中的對(duì)象越多,性能越差于购,跑不動(dòng)
3:頁(yè)面一加載上來(lái)要事先指定DOM的事件處理程序袍睡,導(dǎo)致訪問(wèn)DOM的次數(shù),進(jìn)而延遲了整個(gè)文檔的交互就緒時(shí)間肋僧。
所以:從以上的角度考慮:
解決
1》避免向頁(yè)面中DOM添加大量的事件處理程序斑胜,限制了DOM和js建立連接的數(shù)量。利用委托嫌吠,只是給某個(gè)祖級(jí)指定一個(gè)事件處理程序止潘,來(lái)管理某一類(lèi)的所有事件。例如:管理所有的點(diǎn)擊辫诅。
2》對(duì)于即將移除的DOM凭戴,要手動(dòng)移除其身上的事件處理程序。有些瀏覽器不會(huì)做只能處理釋放掉炕矮,比如:通過(guò)innerHTML方式替換掉的元素么夫。
方案一:利用委托
論證上邊寫(xiě)的很清楚了者冤,下面就是針對(duì)每個(gè)方案上一段代碼吧。
HTML:
<div class="con">
<button id="btn1">點(diǎn)擊我變色</button>
<p id="btn2">點(diǎn)擊出彈窗</p>
<h6 id="btn3">點(diǎn)擊做跳轉(zhuǎn)</h6>
</div>
CSS:
.con {
background: rgba(0, 0, 0, .2);
border: 1px solid #ff9;
}
.btn1, .btn2, .btn3 {
width: 300px;
height: 50px;
border: 1px solid #000;
text-align: center;
line-height: 50px;
cursor: pointer;
}
目標(biāo):
點(diǎn)擊3個(gè)元素走不同的事件處理程序档痪。
分析:
3個(gè)元素共同的祖級(jí)是類(lèi)名叫.con的元素涉枫。所以把事件執(zhí)行程序與他建立聯(lián)系即可。而不是傳統(tǒng)的給每個(gè)元素綁定一次事件處理代碼腐螟。
實(shí)現(xiàn):
JS:
window.onload = function () {
//1:獲取DOM
var btn1 = document.querySelector('#btn1');
var btn2 = document.querySelector('#btn2');
var btn3 = document.querySelector('#btn3');
var con = document.querySelector('.con');
//2:事件委托
con.addEventListener('click', function (e) {
var e = e || event;
if (e.target.id == 'btn1') {
//換背景色
con.style.background = '#80B3FF';
}
if (e.target.id == 'btn2') {
//彈出目標(biāo)的id
alert(e.target.id);
}
if (e.target.id == 'btn3') {
//做跳轉(zhuǎn)
window.location.;
}
}, true)
}
===================================================
tip:
這里是通過(guò)事件對(duì)象的里的target對(duì)象里的id屬性愿汰,當(dāng)然這種在實(shí)際開(kāi)發(fā)事使用較少,畢竟要給每個(gè)元素一個(gè)id乐纸,id甚是寶貴衬廷,不能亂來(lái),所以汽绢,再看看通過(guò)其他方式選中你要操作的元素吗跋。普通元素還可以通過(guò)節(jié)點(diǎn)名(標(biāo)簽名),標(biāo)簽內(nèi)容庶喜。表單元素還可以通過(guò)name屬性小腊,例如這里的button按鈕救鲤。標(biāo)簽身上設(shè)置下name屬性久窟。js里根據(jù)這個(gè)屬性去拿到對(duì)應(yīng)DOM。
===================================================
通過(guò)其他方式拿到對(duì)應(yīng)的DOM
1.標(biāo)簽名:
HTML:
<div class="con">
<button>點(diǎn)擊我變色</button>
<p>點(diǎn)擊出彈窗</p>
<h6>點(diǎn)擊做跳轉(zhuǎn)</h6>
</div>
這里省略樣式本缠,和上邊一致的斥扛。.con里的子只有標(biāo)簽名字。
JS:
window.onload = function () {
var btn1 = document.querySelector('button');
var btn2 = document.querySelector('p');
var btn3 = document.querySelector('h6');
var con = document.querySelector('.con');
con.addEventListener('click', function (e) {
var e = e || event;
if (e.target.nodeName.toLowerCase() == 'button') {
//換背景色
con.style.background = '#80B3FF';
}
if (e.target.nodeName.toLowerCase() == 'p') {
//彈出目標(biāo)的id
alert(e.target.nodeName);
//二者是一致的
alert(e.srcElement.nodeName);
}
if (e.target.nodeName.toLowerCase() == 'h6') {
//做跳轉(zhuǎn)
window.location.;
}
}, true)
}
e.target.nodeName拿到的是大寫(xiě)的標(biāo)簽名字丹锹,所以需要轉(zhuǎn)換成小寫(xiě)好處理些稀颁。toLowerCase()一下就OK了。
2.標(biāo)簽內(nèi)容:
HTML:
<div class="con">
<button>點(diǎn)擊我變色</button>
<p>點(diǎn)擊出彈窗</p>
<h6>點(diǎn)擊做跳轉(zhuǎn)</h6>
</div>
JS:
window.onload = function () {
var con = document.querySelector('.con');
con.addEventListener('click', function (e) {
var e = e || event;
if (e.target.innerHTML == '點(diǎn)擊我變色') {
//換背景色
con.style.background = '#80B3FF';
}
if (e.target.innerHTML == '點(diǎn)擊出彈窗') {
//彈出目標(biāo)的id
alert(e.target.nodeName);
//二者是一致的
alert(e.srcElement.nodeName);
}
if (e.target.innerHTML == '點(diǎn)擊做跳轉(zhuǎn)') {
//做跳轉(zhuǎn)
window.location.;
}
}, true)
}
利用 e.target.innerHTML或者是e.target.innerText都可以楣黍。
3.表單標(biāo)簽的name屬性:
如果是表單元素匾灶,還可以在表單元素上把name屬性設(shè)置下。
HTML:
<div class="con">
<button name="fromDomBtn">點(diǎn)擊我變色</button>
<p>點(diǎn)擊出彈窗</p>
<h6>點(diǎn)擊做跳轉(zhuǎn)</h6>
</div>
JS:這里只是寫(xiě)按鈕部分了租漂。
con.addEventListener('click', function (e) {
var e = e || event;
if (e.target.name == 'fromDomBtn') {
//換背景色
con.style.background = '#80B3FF';
}
}
利用表單身上的屬性name;即e.target.name
常規(guī)處理方式就是以上幾種阶女,可以根據(jù)你的代碼選擇合適的方案。
方案二:手動(dòng)移除事件處理程序
如果心里清楚哩治,哪些帶有事件處理程序的元素將要被移除秃踩,那么最好手動(dòng)置空他的事件處理程序,即切斷了DOM和js之間的引用關(guān)系业筏。如果直接對(duì)DOM進(jìn)行增刪改查中的“刪”憔杨,即:removeChild()/replaceChild()等,是不需要咱們手動(dòng)再置空他們身上原來(lái)的事件引用蒜胖。因?yàn)榍岸说拇a一般不需要我們進(jìn)行內(nèi)存管理消别、垃圾回收等操作抛蚤,瀏覽器會(huì)幫我們做好。這里說(shuō)的將要被移除是指通過(guò)innerHTML的方式替換達(dá)到刪除的結(jié)果寻狂,此時(shí)就需要我們做點(diǎn)事了霉颠,因?yàn)橐恍g覽器不會(huì)很好的處理這一塊,例如(IE)荆虱;下邊用代碼演示下具體怎么實(shí)現(xiàn):
HTML:
<div class="con">
<button>點(diǎn)擊我發(fā)生con的內(nèi)容替換</button>
</div>
JS:
window.onload = function () {
var con = document.querySelector('.con');
var btn = document.querySelector('button');
const txt = ` <h1>Lorem ipsum dolor.</h1>
<p> Error esse est illo impedit libero molestias, perspiciatis ratione repudiandae voluptate voluptatem!</p>`;
btn.onclick = function () {
btn.onclick = null;//點(diǎn)擊進(jìn)來(lái)后手動(dòng)釋放自身和事件處理程序的引用關(guān)系蒿偎;用過(guò)一次就釋放掉了
con.innerHTML = txt;
}
}
把這段代碼,復(fù)制到你的編譯器試試吧怀读,點(diǎn)擊事件肯定只會(huì)執(zhí)行一次诉位。
js庫(kù)實(shí)現(xiàn)委托
如果你不是使用原生js,使用jQuery或是zepto等怎么做呢菜枷?更簡(jiǎn)單苍糠。直接上代碼。
HTML片段截绕√堋:
![](/gameInfo/images/ban.jpg)
<a href="###" class="loadBtn hrefTo"></a>
<b class="clickDetail hrefTo">(點(diǎn)擊了解詳情)</b>
由于jQuery/zepto里自帶的事件注冊(cè)on方法只能接受3個(gè)參數(shù)岳瞭,所以對(duì)于第二個(gè)參數(shù)DOM;要好好利用下了蚊锹,把需要的做同一件事的dom都附屬一個(gè)類(lèi)名叫:hrefTo的瞳筏。OK。
//1:引入庫(kù)
<script src="/common/js/zepto.min.js"></script>
//2:點(diǎn)擊banner/了解詳情/下載按鈕三處實(shí)現(xiàn)跳轉(zhuǎn)
$('body').on('click','.hrefTo',function () {
window.location.;
});
----------------------------------------------------喜歡就動(dòng)動(dòng)小手哈牡昆。------------------------------------------------------
--------------------------------------你的支持是灑家-麥殼-macrolam前進(jìn)的動(dòng)力--------------------------------------