• Javascript事件处理机制


    刚学JS的时候就用到了事件,可是却一直没去弄懂是什么原理。各种笔面试中不乏有这问题,整理一下。

    一、什么是JS的事件

     事件的定义

     惯例,事件什么?

     

    ...

    ...

    ...

    来个严谨一点的定义:

    事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间。

    OK,JS是事件呢。其实就是我们经常接触到的,点击按钮,鼠标悬停之类。

    二、事件流

    在事件流的概念上,最初两大浏览器厂商IE和Netscape的定义截然不同。

    1、事件冒泡

     事件冒泡是IE定义的事件流,即事件开始由最具体的元素(例如点击事件中的点击对象)接收,然后逐级向上传播。

    2、事件捕获

    事件捕获却是认为最不具体的节点最早接收到事件,然后逐级向下传播。

    3.DOM事件流

    现在新版本的浏览器都采用了DOM事件流的概念。

    包括三个阶段:

    • 事件捕获阶段
    • 处于目标阶段
    • 事件冒泡阶段

    按顺序执行以上各阶段。

    三、事件处理的四个方式

    1、HTML事件处理程序

    接在HTML代码中添加事件处理程序

    <input id="btn" type="button" onclick="clickme(this)">
    <script> var btn = document.getElementById("btn"); btn.value = "点我阿~~~"; var text = ["咋了", "点我干嘛", "还点", "不理你了"]; var time = 0; function clickme(e) { if (time > 3 && time < 12) { e.value = "哼"; } else if (time > 11) { e.value = "fuck"; } else { for (var i in text) { e.value = text[time]; } } time++; } </script>

    2、DOM0级事件处理程序

    相比第一种,DOM0级事件处理直接对于制定对象添加事件。

    <input id="btn" type="button">
    <script> var btn = document.getElementById("btn"); btn.value = "点我阿~~~"; var text = ["咋了", "点我干嘛", "还点", "不理你了"]; var time = 0; btn.onclick = function(){ if (time > 3 && time < 12) { this.value = "哼"; } else if (time > 11) { this.value = "fuck"; } else { for (var i in text) { this.value = text[time]; } } time++; } </script>
    • 如若要删除该事件,可直接将其值设为null

    btn.onclick = null;

    3、DOM2级事件处理程序

     DOM2级事件处理程序定义了两个方法,addEventListener()和removeEventListener().字面即可理解为事件的添加和删除。

    <button id="btn-bind">绑定事件</button>
    <script>
        function clickme() {
            alert("美丽最傻");
        }
        document.getElementById("btn-bind").addEventListener("click", clickme, false);
        document.getElementById("btn-bind").removeEventListener("click", clickme, false);
    </script>
    

    显而易见。这两个方法都带有三个参数:

    • 要处理的事件名
    • 作为事件处理程序的函数
    • 一个布尔值

    解释一下这几个参数:

    第一个处理的事件名同上两个处理程序相比,事件名不带on,即点击事件是'click'。

    第二个参数是一个函数,这里有一个注意的地方,如果是是采用function(){...}的方式作为第二个参数传入,那是无效的。因为实际上是传入了两个完全不同的函数。

    第三个参数,当布尔值为true的时候,表示在事件捕获阶段调用该处理程序,反之则表示在事件冒泡阶段调用。一般建议添加在事件冒泡阶段,为了更好的兼容浏览器。

    关于事件捕获和事件冒泡等下说。

    4、IE事件处理程序

    IE的事件处理程序类似DOM,拥有两个方法,attchEvent()和detachEvent()

    <button id="btn-bind">绑定事件</button>
    <script>
        function clickme() {
            alert("美丽最傻");
        }
        document.getElementById("btn-bind").attachEvent("click",clickme);
        document.getElementById("btn-bind").detachEvent("click",clickme);
    </script>
    

    有没有发现,其实和DOM2处理程序很相像,只是少了一个参数,由于次方法是针对于IE8及其更早版本的浏览器,所以只支持事件冒泡。

    现在浏览器普遍只是DOM2级事件处理,但是由于要兼顾兼容性的问题,还是需要了解这个方法。

    四、事件的浏览器兼容性问题

    上一节了解了四种处理程序的方法。下面就总结一下,贴一个兼容各浏览器的代码。

    var EventUtil = {
            addHandler:function(element,type,handler) {
                //body
            },
            getEvent:function(event){
                return event ? event : window.event;
            },
            getTarget:function(event){
                return event.target || event.srcElement;
            },
            preventDefault:function(event){
                if(event.preventDefault){
                    event.preventDefault();
                }eles{
                    event.returnValue = false;
                }
            },
    
            removeHandler:function(element,type,handler){
                //body
            },
            stopPropagation:function(event){
                if(event.stopPropagation){
                    event.stopPropagation();
                }else{
                    event.cancelBubble = true;
                }
            }
        };
    

      

    代码来自《Javascript高级程序设计》(第3版)

    五、事件冒泡引发的问题

    先贴一段代码

    <div id="wrap">
            <div id="content">
                <div id="father">
                    Father
                    <div id="son">Son</div>
                </div>
            </div>
        </div>
    <script>
        var father = document.getElementById("father");
        var son = document.getElementById("son");
        father.onclick = function() {
            alert("I'm father");
        }
        son.onclick = function() {
            alert("I'm son");
        }
    </script>
    

    上面的栗子中,当我点击了id为son的div之后,点击事件往上传递,这时候就会有引发一个问题,我在id为father上也加了一个点击事件,当son的冒泡事件往上传递到father的时候,同时也触发了father的点击事件,所以会分别alert出“im son”和“i'm father“

    在实际应用当中也会有这种困扰,所以这时候我们需要阻止事件冒泡。

    <div id="wrap">
            <div id="content">
                <div id="father">
                    Father
                    <div id="son">Son</div>
                </div>
            </div>
        </div>
        <script>
        function stopEventBubble(event){
            var e=event || window.event;
            if (e && e.stopPropagation){
                e.stopPropagation();    //针对除IE外浏览器
            }
            else{
                e.cancelBubble=true;  //针对IE浏览器
            }
        }
        var father = document.getElementById("father");
        var son = document.getElementById("son");
        father.onclick = function() {
            alert("I'm father");
        }
        son.onclick = function(e) {
            alert("I'm son");
            stopEventBubble(e)
        }
        </script>
  • 相关阅读:
    xlrd doc
    安装Python package
    Python处理Excel(转载)
    OPENSSL简介
    sublime text2教程
    使用SQL 从表中取记录
    SQL基础
    shell脚本之grep的使用方法
    (转载)(收藏)OceanBase深度解析
    (转载)线程池的使用
  • 原文地址:https://www.cnblogs.com/ellenwu/p/4939965.html
Copyright © 2020-2023  润新知