# 事件机制、事件模型、事件流

# 一、基本概念,DOM事件的级别

DOM0 element.onclick=function(){}

DOM2 element.addEventListener('click',function(){},false)

DOM3 element.addEventListener('keyup',function(){},false)

# 二、DOM事件模型

捕获和冒泡,捕获是从上到下,冒泡是从下到上。

# 三、DOM事件流

捕获阶段-》目标阶段-》冒泡阶段

# 四、描述DOM事件捕获的具体流程

window->document->html->body->一层一层传给指定dom元素->目标元素

# 五、Event对象的常见应用

event.preventDefault();

event.stopPropagation();

event.stopImmediatePropagation(); // 事件响应优先级,比如为同一个btn设置了click事件响应函数A和B,那么在点击btn的时候,就会同时触发A和B,如果想执行完A就不执行B了,就可以用这个方法。

event.currentTarget; // 当前绑定的dom

event.target; // 目标元素

# 六、自定义事件

var eve=new Event('custome');
el.addEventListener('custome',function(){
    console.log('test')
})
el.dispatchEvent(eve);
1
2
3
4
5

除了Event,还有CustomEvent,CustomEvent相比于Event,可以传递数据。

# 七、事件委托

委托(代理)事件是那些被绑定到父级元素的事件,但是只有当满足一定匹配条件时才会被挪。这是靠事件的冒泡机制来实现的,

优点是:

(1)可以大量节省内存占用,减少事件注册,比如在table上代理所有td的click事件就非常棒

(2)可以实现当新增子对象时无需再次对其绑定事件,对于动态内容部分尤为合适

缺点是:

事件代理的应用常用应该仅限于上述需求下,如果把所有事件都用代理就可能会出现事件误判,即本不应用触发事件的被绑上了事件。

手写原生js实现事件代理,并要求兼容浏览器

function delegateEvent(interfaceEle, selector, type, fn) {
    if(interfaceEle.addEventListener){
        interfaceEle.addEventListener(type, eventfn);
    }else{
        interfaceEle.attachEvent("on"+type, eventfn);
    }
      
    function eventfn(e){
        var e = e || window.event;   
        var target = e.target || e.srcElement;
        if (matchSelector(target, selector)) {
                if(fn) {
                    fn.call(target, e);
                }
            }
        }
    }
}
/**
 * only support #id, tagName, .className
 * and it's simple single, no combination
 */
function matchSelector(ele, selector) {
    // if use id
    if (selector.charAt(0) === "#") {
        return ele.id === selector.slice(1);
    }
    // if use class
    if (selector.charAt(0) === ".") {
        return (" " + ele.className + " ").indexOf(" " + selector.slice(1) + " ") != -1;
    }
    // if use tagName
    return ele.tagName.toLowerCase() === selector.toLowerCase();
}
//调用
var odiv = document.getElementById("oDiv");
delegateEvent(odiv,"a","click",function(){
    alert("1");
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Last Updated: 2/11/2020, 9:39:58 AM