委托模式(Entrust):多个对象接收并处理同一请求,他们将请求委托给另一个对象统一处理请求。
事件流就是委托模式的一个典型的例子,事件流从捕获开始,到触发该事件,再到事件冒泡三个阶段。
可以将子元素的事件委托给更高层面上的父元素去绑定执行事件委托是一种提高程序性能,降低内存空间的技术手段,它利用了事件冒泡的特性,只需要在某个祖先元素上注册一个事件,就能管理其所有后代元素上同一类型的事件。
用一个例子来描述委托,先创建一个HTML文档,包含一个容器元素
<div id="delegation"> <button type="button">提交</button> <button type="button">返回</button> <button type="button">重置</button> </div>
然后只要给容器元素注册点击事件,它的3个子元素也就能执行这个点击事件,这其实就是一种委托,再通过事件对象的target属性,就能分辨出当前运行在哪个事件目标上。
var container = document.getElementById("delegation") container.addEventListener("click",function(event) { event.target; },false);
使用委托后就能避免对容器中的每个子元素进行事件注册,并且如果在容器中动态添加子元素,新加入的子元素也能使用容器元素上注册的事件,而不用单独绑定一次事件处理程序。做到“预测未来”的作用
currentTarget 和 target的区别
target属性指向的是事件目标,currentTarget指向的是正在处理当前事件的对象,发生事件传播时,target指向的可能不是定义时的事件目标,而currentTarget始终指向定义时的事件目标。
例如target可能指向三个不同的button,而currentTarget始终指向div。
委托模式还能处理一些内存外泄的问题,老版本的IE浏览器的引用计数垃圾回收机制,使得那些队DOM元素的引用没有显性清除的数据会遗留在内存中,除非关闭浏览器,否则无法清除。例如:
<div id="btn_container"> <button id="btn">demo</button> </div> var g = function(id){ return document.getElementById(id)} g('btn').onclick = function(){ //g('btn').onclick = null; g('btn_container').innerHTML = '触发了事件'; }
为btn的元素添加绑定事件,再触发时,父元素中重置内容,这样将会将按钮自身覆盖掉,然而g变量保存的元素绑定的click事件没有清除,所以这个事件就会泄露到内存中,所以可以在父元素设置内存前显性地清除事件.然而这个清楚事件地语句在一些标准浏览器中是不需要的,因为他们采用标记清除方式管理自身地内存,所以更好的办法是使用委托模式
g('btn_container').onclick = function(e){ //获取触发事件元素 var target = e && e.target || window.event.srcElement; //判断触发事件元素是否是btn元素 if(target.id === 'btn'){ g('btn_container').innerHTML = '触发了事件'; } }
委托模式优化了页面中的事件绑定,解决了请求与委托者之间的耦合,通过被委托者接收到的请求的处理后,分发给相应的委托者去处理