摘要:可選,布爾值,指定事件是否在捕獲或冒泡階段執(zhí)行,默認冒泡。適用范圍參數(shù)介紹必須,字符串,事件名稱。必須,指定事件觸發(fā)時執(zhí)行的函數(shù)。事件冒泡事件冒泡與事件捕獲恰恰相反,事件冒泡順序是由內(nèi)到外進行事件傳播,直到根節(jié)點。
什么是事件
javascript與HTML之間交互就是通過事件實現(xiàn)的,事件就是文檔或瀏覽器窗口中發(fā)生的一些特定的交互瞬間。事件在瀏覽器中是以對象的形式存在的,即event,觸發(fā)一個事件,就會產(chǎn)生一個事件對象event,該對象包含著所有與事件有關(guān)的信息,包括導致事件的元素、事件的類型以及其他與特定事件相關(guān)的信息。
DOM元素添加事件 1.DOM元素事件屬性 2.javascript腳本添加事件a. element.onclick=function(e){}
b. element.addEventListener(event,function(e),useCapture)
適用范圍:現(xiàn)代瀏覽器(IE9+, Firefox , chorme, safari, opera)
參數(shù)介紹:event必須,事件名稱。(注:不含“on”,比如“click”、“mouseover”等)。function必須,指定事件觸發(fā)時執(zhí)行的函數(shù)。useCapture可選,布爾值,指定事件是否在捕獲或冒泡階段執(zhí)行,默認false(冒泡)。
c. element.attachEvent(event,function(e))
適用范圍:IE 6、7、8
參數(shù)介紹:event 必須,字符串,事件名稱。(注:含“on”,比如“onclick”、“onmouseover”等)。function必須,指定事件觸發(fā)時執(zhí)行的函數(shù)。
擴展:原生Javascript寫法,跨瀏覽器添加事件
var EventUtil = { // 添加事件監(jiān)聽 add: function(element, type, callback){ if(element.addEventListener){ element.addEventListener(type, callback, false); } else if(element.attachEvent){ element.attachEvent("on" + type, callback); } else { element["on" + type] = callback; } } // 移除事件監(jiān)聽 remove: function(element, type, callback){ if(element.removeEventListener){ element.removeEventListener(type, callback, false); } else if(element.detachEvent){ element.detachEvent("on" + type, callback); } else { element["on" + type] = null; } } }
事件冒泡事件冒泡(dubbed bubbling):與事件捕獲恰恰相反,事件冒泡順序是由內(nèi)到外進行事件傳播,直到根節(jié)點。
注:無論是事件捕獲還是事件冒泡,它們都有一個共同的行為,就是事件傳播
阻止事件捕獲/事件冒泡event.stopPropagation() event.stopImmediatePropagation()event.stopPropagation()
會阻止事件繼續(xù)分發(fā)到其他document節(jié)點,但是當前節(jié)點綁定的多個事件會繼續(xù)按注冊的順序執(zhí)行event.stopImmediatePropagation()
不僅阻止事件繼續(xù)分發(fā)到其他document,還會將事件分發(fā)就地停止,在當前事件之后注冊的其他事件,都不會執(zhí)行舉個栗子:此栗子是阻止事件捕獲,阻止事件冒泡原理一樣
//執(zhí)行結(jié)果 alert("div1第一次執(zhí)行"); alert("div1第二次執(zhí)行");事件代理 什么是事件代理//執(zhí)行結(jié)果 alert("div1第一次執(zhí)行");事件代理也可以稱之為事件委托,事件代理就是在祖先級DOM元素綁定一個事件,當觸發(fā)子孫級DOM元素的事件時,利用事件冒泡的原理來觸發(fā)綁定在祖先級DOM的事件。
那這是什么意思呢?網(wǎng)上的各位大牛們講事件代理基本上都用了同一個例子,就是取快遞來解釋這個現(xiàn)象,借花獻佛,大家認真領(lǐng)會一下事件代理到底是一個什么原理:
有三個同事預計會在周一收到快遞。為簽收快遞,有兩種辦法:一是三個人在公司門口等快遞;二是委托給前臺MM代為簽收。現(xiàn)實當中,我們大都采用委托的方案。前臺MM收到快遞后,她會判斷收件人是誰,然后按照收件人的要求簽收,甚至代為付款。這種方案還有一個優(yōu)勢,那就是即使公司里來了新員工,前臺MM也會在收到寄給新員工的快遞后核實并代為簽收。這里其實有2層意思的:
為什么要用事件代理
第一,現(xiàn)在委托前臺的同事是可以代為簽收的,即程序中的現(xiàn)有的dom節(jié)點是有事件的;
第二,新員工也是可以被前臺MM代為簽收的,即程序中新添加的dom節(jié)點也是有事件的。一般來說,dom需要有事件處理程序,我們都會直接給它設(shè)事件處理程序就好了,那如果是很多的dom需要添加事件處理呢?比如我們有100個li,每個li都有相同的click點擊事件,可能我們會用for循環(huán)的方法,來遍歷所有的li,然后給它們添加事件,那這么做會存在什么影響呢?
在JavaScript中,添加到頁面上的事件處理程序數(shù)量將直接關(guān)系到頁面的整體運行性能,因為需要不斷的與dom節(jié)點進行交互,訪問dom的次數(shù)越多,引起瀏覽器重繪與重排的次數(shù)也就越多,就會延長整個頁面的交互就緒時間,這就是為什么性能優(yōu)化的主要思想之一就是減少DOM操作的原因;如果要用事件代理,就會將所有的操作放到j(luò)s程序里面,與dom的操作就只需要交互一次,這樣就能大大的減少與dom的交互次數(shù),提高性能;
每個函數(shù)都是一個對象,是對象就會占用內(nèi)存,對象越多,內(nèi)存占用率就越大,自然性能就越差了(內(nèi)存不夠用,是硬傷),比如上面的100個li,就要占用100個內(nèi)存空間,如果是1000個,10000個呢,那只能呵呵了,如果用事件代理,那么我們就可以只對它的父級(如果只有一個父級)這一個對象進行操作,這樣我們就需要一個內(nèi)存空間就夠了,是不是省了很多,自然性能就會更好。
事件代理的實現(xiàn)在介紹事件代理的方法之前,先來看一段一般方法的栗子:
上面的代碼很簡單,我們看看有多少次的dom操作,首先要找到ul,然后遍歷li,然后點擊li的時候,又要找一次目標的li的位置,才能執(zhí)行最后的操作,每次點擊都要找一次li。
用事件代理的方式來實現(xiàn),上栗子:
window.onload = function(){ var ulDelegate= document.getElementById("ulDelegate"); ulDelegate.onclick = function(){ alert("Delegate"); } }
這里用父級ul做事件處理,當li被點擊時,由于冒泡原理,事件就會冒泡到ul上,因為ul上有點擊事件,所以事件就會觸發(fā),當然,這里當點擊ul的時候,也是會觸發(fā)的。
那么問題就來了,如果我想讓事件代理的效果跟直接給節(jié)點的事件效果一樣怎么辦,比如說只有點擊li才會觸發(fā),這時,Event對象就派上用場了,Event提供了一個屬性叫target,可以返回事件的目標節(jié)點,我們稱為事件源,也就是說,target就可以表示為當前的事件操作的dom,但是不是真正操作dom,這個是有兼容性的,標準瀏覽器用ev.target,IE瀏覽器用event.srcElement,此時只是獲取了當前節(jié)點的位置,并不知道是什么節(jié)點名稱,這里我們用nodeName來獲取具體是什么標簽名,這個返回的是一個大寫的,我們可以轉(zhuǎn)成小寫再做比較,或者不轉(zhuǎn)。
window.onload = function(){ var ulDelegate= document.getElementById("ulDelegate"); ulDelegate.onclick = function(ev){ var ev = ev || window.event; var target = ev.target || ev.srcElement; if(target.nodeName.toLowerCase() == "li"){ alert("Delegate"); alert(target.innerHTML); } } }
這樣就只有點擊li會觸發(fā)事件了,且每次只執(zhí)行一次dom操作,如果li數(shù)量很多的話,將大大減少dom的操作,優(yōu)化的性能可想而知!
上面的栗子是說li操作的是同樣的效果,如果每個li被點擊的效果都不一樣,上栗子:
再來最后一個事件代理的栗子,當我們新增一個li元素的時候,同樣先看一下一般寫法:
再來看一下事件代理的寫法:
window.onload = function(){ var ulDelegate = document.getElementById("ulDelegate"); var addLi = document.getElementById("addLi"); ulDelegate.onclick = function(ev){ var ev = ev || window.event; var target = ev.target || ev.srcElement; if(target.nodeName.toLowerCase() == "li"){ alert("Delegate"); alert(target.innerHTML); } }; addLi.onclick = function(){ var addLiElement = document.createElement("li"); addLiElement .innerHTML = 10000*Math.random(); ulDelegate.appendChild(addLiElement ); } }
看,上面是用事件單例的方式,新添加的子元素是帶有事件效果的,我們不需要去遍歷元素的子節(jié)點,只需要給父級元素添加事件就好了,其他的都是在js里面的執(zhí)行,這樣可以大大的減少dom操作,這才是事件代理的精髓所在。
總結(jié)事件是將javascript與網(wǎng)頁聯(lián)系在一起的主要方式,在使用事件時,需要考慮如下一些內(nèi)存與性能方面的問題。
有必要限制夜歌頁面中事件處理程序的數(shù)量,數(shù)量太多會導致占用大量內(nèi)存,而且也會讓用戶頁面反應(yīng)不夠靈敏
建立在事件冒泡機制之上的時間委托技術(shù),可以有效的減少時間處理程序的數(shù)量
建議在瀏覽器卸載頁面之前移除頁面中的所有事件處理程序
事件是javascript中最重要的主題之一,深入理解事件的工作機制以及它們對性能的影響是至關(guān)重要的
(總結(jié)摘自javascript高級程序設(shè)計第三版)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/109153.html
摘要:而事件循環(huán)是主線程中執(zhí)行棧里的代碼執(zhí)行完畢之后,才開始執(zhí)行的。由此產(chǎn)生的異步事件執(zhí)行會作為任務(wù)隊列掛在當前循環(huán)的末尾執(zhí)行。在下,觀察者基于監(jiān)聽事件的完成情況在下基于多線程創(chuàng)建。 主要問題: 1、JS引擎是單線程,如何完成事件循環(huán)的? 2、定時器函數(shù)為什么計時不準確? 3、回調(diào)與異步,有什么聯(lián)系和不同? 4、ES6的事件循環(huán)有什么變化?Node中呢? 5、異步控制有什么難點?有什么解決方...
摘要:事件事件就是瀏覽器告知程序,用戶的行為,用戶點擊了頁面中的某個按鈕或者用戶輸入用戶名或密碼等操作可以稱為事件事件的類型事件根據(jù)使用的場景不同,可以分為如下幾種依賴于設(shè)備的輸入事件鍵盤事件和鼠標事件,這些事件都是直接和設(shè)備相關(guān)的獨立于設(shè)備的輸 事件 事件就是瀏覽器告知JavaScript程序,用戶的行為,用戶點擊了HTML頁面中的某個按鈕或者用戶輸入用戶名或密碼等操作可以稱為事件 事件的...
摘要:個人前端文章整理從最開始萌生寫文章的想法,到著手開始寫,再到現(xiàn)在已經(jīng)一年的時間了,由于工作比較忙,更新緩慢,后面還是會繼更新,現(xiàn)將已經(jīng)寫好的文章整理一個目錄,方便更多的小伙伴去學習。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個人前端文章整理 從最開始萌生寫文章的想法,到著手...
摘要:當解釋器尋找引用值時,會首先檢索其在棧中的地址,取得地址后從堆中獲得實體如何實現(xiàn)繼承構(gòu)造繼承原型繼承實例繼承拷貝繼承原型機制或和方法去實現(xiàn)較簡單,建議使用構(gòu)造函數(shù)與原型混合方式。它是基于的一個子集。 JavaScript介紹js的基本數(shù)據(jù)類型。Undefined、Null、Boolean、Number、Stri...
閱讀 1342·2021-09-24 10:26
閱讀 3655·2021-09-06 15:02
閱讀 604·2019-08-30 14:18
閱讀 576·2019-08-30 12:44
閱讀 3119·2019-08-30 10:48
閱讀 1936·2019-08-29 13:09
閱讀 1993·2019-08-29 11:30
閱讀 2279·2019-08-26 13:36