先來上一段我的總結的理解javascript
1/事件分爲三個部分css
(1)捕獲階段html
(2)目標階段java
(3)冒泡階段node
事件冒泡web
1/阻止事件冒泡是對同類名事件而言 (爲何得出這個結論呢:mousedown ,mouseup , mouseove ,fouce,blur 都嘗試寫了阻斷,當時都沒發阻止最上面的onclick的事件發生,後續又試驗了mousedown )瀏覽器
2/事件冒泡的形象圖:性能優化
請注意一點:默認是冒泡的,如果變捕獲,須要改變addEventListener的第三個值
(1):false 默認值 冒泡
(2):true 不冒泡 捕獲dom
事件對象:事件特有的對象,e 是變量名,經常使用的名字,能夠爲任何名字ide
document.onclick = functionl(e){ //e 能夠爲任何名字,建議用e //e有內容 常見的有 // e.target 目標 //e.type 事件類型 ..... //當點擊的內容是document自己,那麼e.target === this //true //當點擊的內容是它內部的div元素,那麼e.target ===this //false}
//事件委託
什麼是委託?
語言的含義: 我把一些感受可讓別人幫忙處理的問題委託給別人處理.
在此處在舉一個例子: 公司前臺MM收快遞
那什麼叫事件委託呢?它還有一個名字叫事件代理,JavaScript高級程序設計上講:事件委託就是利用事件冒泡,只指定一個事件處理程序,就能夠管理某一類型的全部事件。那這是什麼意思呢?網上的各位大牛們講事件委託基本上都用了同一個例子,就是取快遞來解釋這個現象,我仔細揣摩了一下,這個例子 還真是恰當,我就不去想別的例子來解釋了,借花獻佛,我摘過來,你們認真領會一下事件委託究竟是一個什麼原理: 有三個同事預計會在週一收到快遞。爲簽收快遞,有兩種辦法:一是三我的在公司門口等快遞;二是委託給前臺MM代爲簽收。現實當中,咱們大都採用委託的方案(公司也不會容忍那麼多員工站在門口就爲了等快遞)。前臺MM收到快遞後,她會判斷收件人是誰,而後按照收件人的要求籤收,甚至代爲付款。 這種方案還有一個優點,那就是即便公司裏來了新員工(無論多少),前臺MM也會在收到寄給新員工的快遞後覈實並代爲簽收。 這裏其實還有2層意思的: 第一,如今委託前臺的同事是能夠代爲簽收的,即程序中的現有的dom節點是有事件的; 第二,新員工也是能夠被前臺MM代爲簽收的,即程序中新添加的dom節點也是有事件的。 第二個點讓我聯想思考了冒泡事件的第二個階段
事件委託的原理(主要理解target屬性)::
就是利用事件冒泡原理(請先理解冒泡),而後經過target屬性,返回事件的目標節點,稱爲事件源,能夠理解爲target是實際點擊的哪一個標籤(dom),但不是實際的dom.
window.onload = function(){ var oUl = document.getElementById("ul1"); oUl.onclick = function(ev){ var ev = ev || window.event; var target = ev.target || ev.srcElement; if(target.nodeName.toLowerCase() == 'li'){ alert(123); alert(target.innerHTML); } } } 借鑑別人的代碼,真的很經典,點個贊
爲何要用事件委託?
通常來講,dom須要有事件處理程序,咱們都會直接給它設事件處理程序就行了,那若是是不少的dom須要添加事件處理呢?好比咱們有100個li,每一個li都有相同的click點擊事件,可能咱們會用for循環的方法,來遍歷全部的li,而後給它們添加事件,那這麼作會存在什麼影響呢? 在JavaScript中,添加到頁面上的事件處理程序數量將直接關係到頁面的總體運行性能,由於須要不斷的與dom節點進行交互,訪問dom的次數越多,引發瀏覽器重繪與重排的次數也就越多,就會延長整個頁面的交互就緒時間,這就是爲何性能優化的主要思想之一就是減小DOM操做的緣由;若是要用事件委託, 就會將全部的操做放到js程序裏面,與dom的操做就只須要交互一次,這樣就能大大的減小與dom的交互次數,提升性能; 每一個函數都是一個對象,是對象就會佔用內存,對象越多,內存佔用率就越大,天然性能就越差了(內存不夠用,是硬傷,哈哈),好比上面的100個li,就要佔用100個內存空間,若是是1000個,10000個呢,那隻能說呵呵了,若是用事件委託,那麼咱們就能夠只對它的父級(若是隻有一個父級)這一個對象 進行操做,這樣咱們就須要一個內存空間就夠了,是否是省了不少,天然性能就會更好。
這句話讓我有一個深的體會:原先認爲dom的操做,對domj節點的增刪改查,樣式的變化等內容纔會引發瀏覽器的重繪和重排,如今才知道給dom添加節點也會引發瀏覽器的重繪和重排.
我做業中的代碼,能夠執行
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8" /> <title></title> <style> .login-header { width: 100%; text-align: center; height: 30px; font-size: 24px; line-height: 30px; } ul, li, ol, dl, dt, dd, div, p, span, h1, h2, h3, h4, h5, h6, a { padding: 0px; margin: 0px; } .login { width: 512px; height: 280px; position: absolute; left: 0; right: 0; border: #ebebeb solid 1px; background: #ffffff; box-shadow: 0px 0px 20px #ddd; z-index: 9999; display: none;/* overflow: hidden; */ } .login-title { width: 100%; margin: 10px 0px 0px 0px; text-align: center; line-height: 40px; height: 40px; font-size: 18px; position: relative; cursor: move;/* 火狐 */-moz-user-select: none;/*webkit瀏覽器*/-webkit-user-select: none;/*IE10*/-ms-user-select: none;/*早期瀏覽器*/-khtml-user-select: none; user-select: none; } .login-input-content { margin-top: 20px; } .login-button { width: 50%; margin: 30px auto 0px auto; line-height: 40px; font-size: 14px; border: #ebebeb 1px solid; text-align: center; } .login-bg { width: 100%; height: 100%; position: fixed; top: 0px; left: 0px; background: #000000; filter: alpha(opacity=30); opacity: 0.3; display: none; } a { text-decoration: none; color: #000000; } .login-button a { display: block; } .login-input input.list-input {float: left; line-height: 35px; height: 35px; width: 350px; border: #ebebeb 1px solid; text-indent: 5px; } .login-input { overflow: hidden; margin: 0px 0px 20px 0px; } .login-input label {float: left; width: 90px; padding-right: 10px; text-align: right; line-height: 35px; height: 35px; font-size: 14px; } .login-title span { position: absolute; font-size: 12px; right: -20px; top: -30px; background: #ffffff; border: #ebebeb solid 1px; width: 40px; height: 40px; border-radius: 20px; z-index: 99; cursor: pointer; }</style> </head> <body> <div class="login-header"> <a id="link" href="javascript:void(0);">點擊,彈出登陸框</a> </div> <div id="login" class="login"> <div id="title" class="login-title">登陸會員 <span id="closeBtn">關閉</span> </div> <div class="login-input-content"> <div class="login-input"> <label>用戶名:</label> <input type="text"placeholder="請輸入用戶名"name="info[username]"id="username"class="list-input" /> </div> <div class="login-input"> <label>登陸密碼:</label> <input type="password"placeholder="請輸入登陸密碼"name="info[password]"id="password"class="list-input" /> </div> </div> <div id="loginBtn" class="login-button"> <a href="javascript:void(0);" id="login-button-submit">登陸會員</a> </div> </div> <script> // 所有功能 let loginDom = document.querySelector(".login"); let linkDom = document.querySelector(".login-header a"); let closeBtn = document.querySelector("#closeBtn"); let userNameDom = document.querySelector("#username"); let passwordDom = document.querySelector("#password"); let winHeight = window.innerHeight; let winWidth = window.innerWidth; // API: 頁面的寬度和高度 => window.innerWidth window.innerHeight // 1. 顯示login的時候,讓login是水平垂直居中(left、top)不建議用css 會影響到拖拽 let originX = 0; let originY = 0; let logTop = 0; let logLeft = 0; linkDom.addEventListener("click", showFun); function showFun(e) { console.log("showFun"); e.stopPropagation(); loginDom.style.display = "block"; loginDom.style.top = (winHeight - loginDom.offsetHeight) / 2 + "px"; loginDom.style.left = (winWidth - loginDom.offsetWidth) / 2 + "px"; } closeBtn.addEventListener("click", closeFun); function closeFun(e) { loginDom.style.display = "none"; console.log("closeFun"); } document.addEventListener("click", closeFun); loginDom.addEventListener("mousedown", mouseDownFun); function mouseDownFun(e) {// e.stopPropagation();console.log("mouseDownFun"); originX = e.pageX; originY = e.pageY; logLeft = this.offsetLeft; logTop = this.offsetTop; document.addEventListener("mousemove", mouseMoveFun); } function mouseMoveFun(e) { console.log("mouseMoveFun"); loginDom.style.left = e.pageX - originX + logLeft + "px"; loginDom.style.top = e.pageY - originY + logTop + "px"; } loginDom.addEventListener("click", logClickFun); // loginDom.addEventListener("dblclick", logClickFun); function logClickFun(e) {// e.stopPropagation();console.log("logClickFun"); } loginDom.addEventListener("mouseup", mouseUpFun); function mouseUpFun(e) { e.stopPropagation(); console.log("mouseUpFun"); document.removeEventListener("mousemove", mouseMoveFun); } // userNameDom.addEventListener("focus", focusFun); userNameDom.addEventListener("click", userNameFun); function userNameFun(e) { e.stopPropagation(); console.log("userNameFun"); } // function focusFun(e) { // e.stopPropagation(); // console.log("blurFun"); // } // 2. 摁住title區域,實現拖拽效果 // 3. 限制login拖拽的範圍 // 4. 按住esc 鍵也能關閉掉 login // 5. 點擊頁面空白區域關閉也能關掉login</script> </body> </html>
阻斷冒泡是對同類事件起效果的
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <style> .father { width: 100px; height: 100px; background-color: red; } .son { width: 50px; height: 50px; background-color: yellow; }</style> </head> <body> <div class="father"> <div class="son"></div> </div> <script> let fatherDom = document.querySelector(".father"); let sonDom = document.querySelector(".son"); fatherDom.addEventListener("mousedown", fatherFun); function fatherFun(e) { alert("111111"); } sonDom.addEventListener("mousedown", sonFun); function sonFun(e) { e.stopPropagation(); alert("2222222222"); }</script> </body> </html>