核心提示:理解DOM事件流的三个阶段,当点击一个按钮,事实上你还同时点击了按钮所有的父元素。事件流所描述的就是从页面中接受事件的顺序。因为有两种观点,所以事件流也有两种,分别是事件冒泡和事件捕获。现行的主流是事...
理解DOM事件流的三个阶段,当点击一个按钮,事实上你还同时点击了按钮所有的父元素。事件流所描述的就是从页面中接受事件的顺序。因为有两种观点,所以事件流也有两种,分别是事件冒泡和事件捕获。现行的主流是事件冒泡。
事件冒泡
事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为不具体的节点。
简述事件冒泡流程
DOM树形结构 事件冒泡 阻止冒泡 冒泡的应用<meta charset="UTF-8" /> <title></title> <button id="clickMe">Click Me</button> var button = document.getElementById('clickMe'); button.onclick = function() { console.log('1. You click Button'); }; document.body.onclick = function() { console.log('2. You click body'); }; document.onclick = function() { console.log('3. You click document'); }; window.onclick = function() { console.log('4. You click window'); };
如果点击了button,那么这个点击事件会按如下的顺序传播:button>body>document>window
事件捕获的过程相反。
DOM事件流
DOM事件流包括三个阶段。
事件捕获阶段
处于目标阶段
事件冒泡阶段
addEventListener最后一个参数,为true则代表使用事件捕获模式,false则表示使用事件冒泡模式。
用事件冒泡实现代理
a1 a2 a3 a4
var p1=document.getElementById('p1'); p1.addEventListener('click', function(e){ var target=e.target; if(target.nodeName==='A'){ alert(target.innerHTML); } })
完善通用绑定事件的函数
function bindEvent(elem,type,selector,fn){ if(fn==null){ fn=selector selector=null } elem.addEventListener(type, function(e){ var target if(selector){ target=e.target if(target.matches(selector)){ fn.call(target, e) } } else { fn(e) } }) } // 使用代理 var p1=document.getElementById('p1'); bindEvent(p1,'click','a',function (e) { console.log(this.innerHTML) }) // 不使用代理 var a=document.getElementById('a1'); bindEvent(p1,'click',function(e){ console.log(a.innerHTML); })
代理的好处
减少浏览器内存占用
代码整洁