• dom事件机制系列


    JS事件流机制

      一个完整的JS事件流是从window开始,最后回到window的一个过程,事件流被分为三个阶段:

      (1~5)捕获过程、(5~6)目标过程、(6~10)冒泡过程。

      通过addEventListener可以监听冒泡阶段的事件,如果第三个参数指定为true,则监听的是捕获阶段的事件。低版本IE(6,7,8)不支持捕获阶段的事件监听,只能用attachEven来监听冒泡阶段事件。这不意味着低版本IE没有事件捕获,其实有,只不过没办法去监听而已

    attachEvent和addEventListener的对比

    1. 两者都可以为一个元素添加多个事件监听,不会出现覆盖问题
    2. 前者回调函数中this指向window,后者回调函数中this指向当前元素
    3. 前者监听的是事件冒泡,而后者通过第三个参数可以指定为冒泡(默认false)或者捕获(true)
    4. 对于阻止事件冒泡,前者调用e.cancelBubble=true,而后者调用e.stopPropagation()
    5. 事件名不一样:前者“onclick”,而后者“click”
    6. 前者支持IE10及以下(IE11以及以上使用的话,会提示没有这个方法),而后者IE9及以上和非IE浏览器

    阻止默认行为

    标准写法:

    function cancelHandler(event){
        event=event||window.event;//兼容IE
        
        //取消事件相关的默认行为
        if(event.preventDefault)    //标准技术
            event.preventDefault();
        if(event.returnValue)    //兼容IE9之前的IE
            event.returnValue=false;
        return false;    //用于处理使用对象属性注册的处理程序
    }

      因为IE6,7,8回调函数的没有传入参数,而是要通过window.event来获取事件对象;而且ff中没有全局的window.event事件对象,所以兼容的写法就是 event || window.event

      dom0级事件(onclick=xxx)中,使用e.returnValue = false【IE9以上不支持】 、e.preventDefault()【IE6,7,8不支持】或者return false【主要用在dom0级事件中,如onclick=xx】都有效

      dom2级事件(addEventListener)中,使用return false无效

      attachEvent中使用e.preventDefault()无效

    ps:阻止a标签的默认行为

    事件委托

      利用事件冒泡,把对多个子元素的事件监听,转换为对一个父元素的事件监听,可以提升效率(减少内存对象)。其实利用捕获或者冒泡实现都可以,只不过主流浏览器都支持事件冒泡,所以从兼容性的角度来还是选用冒泡。

    <ul id="color-list">
        <li>red</li>
        <li>yellow</li>
        <li>blue</li>
        <li>green</li>
        <li>black</li>
        <li>white</li>
    </ul>
    
    (function(){
        var color_list = document.getElementById('color-list');
        color_list.addEventListener('click',showColor,false);
        function showColor(e){
            var x = e.target;
            if(x.nodeName.toLowerCase() === 'li'){
                alert('The color is ' + x.innerHTML);
            }
        }
    })();

      以上使用委托除了节省了内存外,还有另外一个好处,当动态添加了一个子元素,不需要为这个子元素绑定事件,更加便捷。

    事件目标

    evt中对于事件对象有三个属性:currentTarget、target和srcElement

    currentTarget:代表当前节点,一般与this指向相同。(attachEvent中this指向window)

    target和srcElement:实际发生事件的dom对象。ff不支持srcElement,所以兼容的写法是: var target = e.target || e.srcElement

    事件其他属性

    bubbles:代表当前事件是否会冒泡,除了focus、blur和scroll三种事件不会冒泡之外,其他类型的事件改属性都为true

    cancelBubble:默认为false,设置为true时,用于阻止冒泡,对捕获阶段无效,全浏览器支持,但不是标准写法,应尽量使用stopPropagation

    stopPropagation() :阻止事件在事件流(先捕获后冒泡)中的传播。一种情况例外,如果在A上捕获事件,里面执行stopPropagation,则A的冒泡回调也会执行:

    <div id="a">
        123
        <div id="b">
            456
            <div id="c">
                789
            </div>
        </div>
    </div>
    <script>
        var a = document.querySelector("#a");
        var b = document.querySelector("#b");
        var c = document.querySelector("#c");
    
        a.addEventListener('click',(e)=>{
            console.log("a")
    
        },true)
    
        b.addEventListener('click',(e)=>{
            console.log("b")
            e.stopPropagation()
        },true)
    
        c.addEventListener('click',(e)=>{
            console.log("c")
        },true)
    
        a.addEventListener('click',(e)=>{
            console.log("2 a")
        })
    
        b.addEventListener('click',(e)=>{
            console.log("2 b")
        })
    
        c.addEventListener('click',(e)=>{
            console.log("2 c")
        },true)
    </script>
    点击456,输出 a b 2b。
    View Code

    stopImmediatePropagation():在阻止事件传播的基础上,同时阻止当前元素上对同一事件的其他回调函数的执行

    总结低版本IE与其他浏览器的事件差异

    1. 获取事件对象的方式不同
    2. 取消默认行为的方式不同
    3. 可以检测控制的事件流不同
  • 相关阅读:
    【JAVA】 04-Java中的多线程
    【刷题】经典的启发式算法
    【刷题】java 常见的几种运行时异常RuntimeException
    【学习总结】认识微服务
    【刷题】知识点与易错点之简单编程思路总结
    【刷题】知识点与易错点- 总
    【刷题】知识点与易错点之数据结构
    【学习总结】《大话数据结构》- 第9章-排序
    LeetCode之“动态规划”:Valid Parentheses && Longest Valid Parentheses
    LeetCode之“动态规划”:Interleaving String
  • 原文地址:https://www.cnblogs.com/hellohello/p/7985927.html
Copyright © 2020-2023  润新知