zoukankan      html  css  js  c++  java
  • 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>
  • 相关阅读:
    ASP.NET Web API 框架研究 Self Host模式下的消息处理管道
    ASP.NET Web API 框架研究 Web Host模式下的消息处理管道
    ASP.NET Web API 框架研究 核心的消息处理管道
    ASP.NET Web API 框架研究 Web Host模式路由及将请求转出到消息处理管道
    ASP.NET Web API 框架研究 ASP.NET Web API 路由
    ASP.NET Web API 框架研究 ASP.NET 路由
    ASP.NET Web API 入门 (API接口、寄宿方式、HttpClient调用)
    MVVM模式
    RESTful Web API 理解
    C# 函数式编程及Monads.net库
  • 原文地址:https://www.cnblogs.com/ellenwu/p/4939965.html
Copyright © 2011-2022 走看看