事件捕获:事件从最不精确的对象(document对象)开始触发,然后到最精确
事件冒泡:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发
不是所有事件都能冒泡。以下事件不冒泡:blur、focus、load、unload(关闭页面)
事件委托(代理):不在事件的发生地(直接dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素DOM的类型,来做出不同的响应。
为什么要用事件委托:
在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能;
事件委托怎么实现:
举例:最经典的就是ul和li标签的事件监听,比如我们在添加事件时候,采用事件委托机制,不会在li标签上直接添加,而是在ul父元素上添加。
**好处:**比较合适动态元素的绑定,新添加的子元素也会有监听函数,也可以有事件触发机制。
// 通用的事件绑定函数
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;
// matches 用来判断当前DOM节点能否完全匹配对应的CSS选择器规则;
// 如果匹配成功,返回true,反之则返回false。
if (target.matches(selector)) {
fn.call(target, e);
}
} else {
fn(e);
}
})
}
// 使用代理
var div1 = document.getElementById('div1');
bindEvent(div1, 'click', 'a', function(e){
console.log(this.innerHtml);
})
// 不使用代理
var a = document.getElementById('a1');
bindEvent(a, 'click', function(e){
console.log(a.innerHtml);
})