Heim > Web-Frontend > js-Tutorial > Detaillierte Erklärung des DOM-Ereignisflusses in js

Detaillierte Erklärung des DOM-Ereignisflusses in js

小云云
Freigeben: 2018-03-20 17:46:30
Original
1828 Leute haben es durchsucht

Ein Ereignis ist eine Aktion, die vom Benutzer oder vom Browser selbst ausgeführt wird. Wie zum Beispiel Klicken, Laden, Mouseover. Der Ereignisfluss beschreibt die Reihenfolge, in der Ereignisse von der Seite empfangen werden, und kann auch als die Reihenfolge verstanden werden, in der Ereignisse auf der Seite verbreitet werden. Event-Handler Eine Funktion, die auf ein Ereignis reagiert, wird Event-Handler (oder Event-Listener) genannt.

Ereignishandler auf DOM0-Ebene

Das folgende Beispiel zeigt zwei Methoden zum Binden von Ereignissen in dom0 und wie man die Bindung von Ereignissen aufhebt. Beim Ausführen des Codes stellen wir fest, dass zwei Ereignisse an dasselbe Element gebunden sind gleichzeitig Wenn dies der Fall ist, überschreibt das später gebundene Ereignis das früher gebundene Ereignis.

<!DOCTYPE html>
<html>
<head>
   <meta charset="UTF-8">
   <title>Title</title>
</head>
<body>
       <button type="button" id="btn" onclick="alert(&#39;btn1&#39;)">点击按钮</button>
</body>
<script>    var btn=document.getElementById("btn");    //绑定事件    btn.onclick=function(){        alert("btn");
   };    //事件解绑    btn.onclick=null;
</script>
</html>
Nach dem Login kopieren

Ereignishandler auf Dom2-Ebene

<!DOCTYPE html>
<html>
<head>
   <meta charset="UTF-8">
   <meta name="viewport"          content="width=device-width, initial-scale=1.0, maximum-scale=1.0,minimum-scale=1.0,user-scalable=0"/>
   <title>Title</title>
</head>
<body>
<button type="button" id="btn" onclick="alert(&#39;btn1&#39;)">点击按钮</button>
</body>
<script>    var btn=document.getElementById("btn");    //绑定事件    btn.addEventListener("click",function(){         alert("btn");
   },false);    //事件解绑   btn.removeEventListener("click",function(){       alert("解绑");
  })
</script>
</html>
Nach dem Login kopieren

Hinweis: Der dritte Parameter der Methode addEventListener() ist standardmäßig auf false gesetzt, d. h. das Programm wird in Form von Event-Bubbling ausgeführt . Wenn dies der Fall ist, verwenden Sie die Ereigniserfassung, um das Programm auszuführen. IE-Browser sind auf Nicht-IE-Browser beschränkt und verwenden attachmentEventListener zum Binden von Ereignissen. Bezüglich der Bindung und Aufhebung der Bindung von Ereignissen in IE- und Nicht-IE-Browsern werde ich ein Beispiel schreiben, um den Unterschied zwischen den beiden zu zeigen.

var eventUtil = {    //添加事件    addEventHandle:function(element,eventType,fn){        if(element.addEventListener){//非IE            element.addEventListener(eventType,fn,false);
       }else if(element.attachEvent){//IE            element.attachEvent(&#39;on&#39;+eventType,fn);//这里拼接上&#39;on&#39;,调运的时候不要加on,使用click等。        }else{//不支持DOM2级,使用DOM0级方式            element[&#39;on&#39;+eventType] = fn;//这里使用[]方式实现对象的属性添加,相当于.的作用        }
   },    //删除事件    removeEventHandle:function(element,eventType,fn){        if(element.removeEventListener){//非IE,不带&#39;on&#39;            element.removeEventListener(eventType,fn,false);
       }else if(element.detachEvent){//IE,带&#39;on&#39;            element.detachEvent(&#39;on&#39;+eventType,fn);
       }else{//不支持DOM2级,使用DOM0级方式            element[&#39;on&#39;+eventType] = fn;
       }
   },    //获取事件对象    getEvent:function(event){        return event?event:window.event;
   },    //获取事件类型    getType:function(event){        return event.type;
   },    //获取执行事件的目标元素    getTarget:function(event){        return event.target||event.srcElement;
   },    //禁用默认行为    preventDefault:function(event){        if(event.preventDefault){            event.preventDefault();//非IE        }else{            event.returnValue = false;//针对IE        }

   },    //阻止传播冒泡    stopPropagation:function(event){        if(event.stopPrapagation){            event.stopPropagation();//非IE        }else{            event.cancelBubble = true;//针对IE        }
   }
}
Nach dem Login kopieren

dom3事件处理程序

DOM浏览器中可能发生的事件有很多种,不同事件类型具有不同的信息,DOM3级事件规定了一下几种事件:
UI事件,当用户与页面上的元素交互时触发;
焦点事件,当元素获得或者失去焦点时触发;
鼠标事件,当用户通过鼠标在页面上执行操作时触发;
滚轮事件,当使用鼠标滚轮(或类似设备)时触发;
文本事件,当在文档中,输入文本时触发;
键盘事件,当用户通过键盘在页面上执行操作时触发;
合成事件,当为IME(Input Method Editor,输入法编辑器)输入字符时触发;
变动事件,当底层Dom结构发生变化时触发;
DOM3级事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件。包括IE9在内的主流浏览器都支持DOM2级事件,IE9也支持DOM3级事件。
DOM中的事件模拟(自定义事件):
DOM3级还定义了自定义事件,自定义事件不是由DOM原生触发的,它的目的是让开发人员创建自己的事件。要创建的自定义事件可以由createEvent("CustomEvent");
返回的对象有一个initCustomEvent()方法接收如下四个参数。
1)type:字符串,触发的事件类型,自定义。例如 “keyDown”,“selectedChange”;
2)bubble(布尔值):标示事件是否应该冒泡;
3)cancelable(布尔值):标示事件是否可以取消;
4)detail(对象):任意值,保存在event对象的detail属性中;
可以像分配其他事件一样在DOM中分派创建的自定义事件对象。如:

   
var  p = document.getElementById("myp");
EventUtil.addEventHandler(p,"myEvent", function () {
alert("p myEvent!");
});
EventUtil.addEventHandler(document,"myEvent",function(){
alert("document myEvent!");
});
if(document.implementation.hasFeature("CustomEvents","3.0")){
var e = document.createEvent("CustomEvent");
e.initCustomEvent("myEvent",true,false,"hello world!");
p.dispatchEvent(e);
}
Nach dem Login kopieren

这个例子中创建了一个冒泡事件“myEvent”。而event.detail的值被设置成了一个简单的字符串,然后在p和document上侦听该事件,因为在initCustomEvent中设置了事件冒泡。所以当p激发该事件时,浏览器会将该事件冒泡到document。
IE中的事件模拟(IE8及之前版本中):
与DOM中事件模拟的思路类似,先创建event对象,再为其指定相应信息,然后再使用该对象来触发事件。当然IE在实现以下每个步骤都不太一样。
例如:

var btn = document.getElementById("myBtn");
//创建事件对象,不接受任何参数,结果会返回一个通用的event对象,你必须为该event对象指定所有必要的信息。
var event  = document.createEventObject();
//初始化事件对象
event.screenX = 100;
event.screenY = 0;
event.clientX = 0;
event.clientY =0;
event.ctrlKey = false;
event.altKey = false;
event.shiftKey = false;
event.button = 0;

//触发事件
btn.fireEvent("onclick",event);
Nach dem Login kopieren

事件流的分类

  • 事件冒泡流:IE的事件流叫事件冒泡,即事件开始时由最具体的元素(文档中嵌套层次最深的节点)接收,然后逐级向上传播到较为不具体的节点

  • 事件捕获流:Netscape团队提出的另一种事件流叫事件捕获,事件捕获的思想是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件

  • dom事件流:DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段==>处于目标阶段==>事件冒泡阶段。首先发生的是事件捕获阶段,为截获事件提供了机会。然后是实际的目标接收事件。最后一个阶段是冒泡阶段。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
       <p id="node1">
           <p id="node2">
               <p id="node3">
                   <p id="node4">click me</p>
               </p>
           </p>
       </p>
</body>
<script>    var node1=document.getElementById("node1");    var node2=document.getElementById("node2");    var node3=document.getElementById("node3");    var node4=document.getElementById("node4");    node1.addEventListener("click",function(){        alert("node1");
    },false);    node2.addEventListener("click",function(){        alert("node2");
    },false);    node3.addEventListener("click",function(){        alert("node3");
    },false);    node4.addEventListener("click",function(){        alert("node4");
    },false);
</script>
</html>
Nach dem Login kopieren

以上代码分别给node1-node4个节点绑定事件,且采用事件冒泡的形式执行,从而分别会弹出node4->node3->node3->node1

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
       <p id="node1">
           <p id="node2">
               <p id="node3">
                   <p id="node4">click me</p>
               </p>
           </p>
       </p>
</body>
<script>    var node1=document.getElementById("node1");    var node2=document.getElementById("node2");    var node3=document.getElementById("node3");    var node4=document.getElementById("node4");    node1.addEventListener("click",function(){        alert("node1");
    },true);    node2.addEventListener("click",function(){        alert("node2");
    },true);    node3.addEventListener("click",function(){        alert("node3");
    },true);    node4.addEventListener("click",function(){        alert("node4");
    },true);
</script>
</html>
Nach dem Login kopieren

以上代码分别给node1-node4个节点绑定事件,且采用事件捕获的形式执行,从而分别会弹出node1->node2->node3->node4.

那如果给同一元素同事绑定两个事件,一个采用冒泡一个采用捕获则程序会按照dom流的形式来执行程序即"先捕获后冒泡"

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
       <p id="node1">
           <p id="node2">
               <p id="node3">
                   <p id="node4">click me</p>
               </p>
           </p>
       </p>
</body>
<script>    var node1=document.getElementById("node1");    var node2=document.getElementById("node2");    var node3=document.getElementById("node3");    var node4=document.getElementById("node4");    node1.addEventListener("click",function(){        alert("node1");
    },false);    node2.addEventListener("click",function(){        alert("node2");
    },false);    node3.addEventListener("click",function(){        alert("node3");
    },false);    node4.addEventListener("click",function(){        alert("node4");
    },false);    
    
    node1.addEventListener("click",function(){        alert("node1");
    },true);    node2.addEventListener("click",function(){        alert("node2");
    },true);    node3.addEventListener("click",function(){        alert("node3");
    },true);    node4.addEventListener("click",function(){        alert("node4");
    },true);
    
    
</script>
</html>
Nach dem Login kopieren

程序执行顺序:node1->node2->node3->node4->node4->node3->node2->node1.

事件代理

含义:事件代理即事件委托,就是利用事件冒泡只制定一个事件处理程序就可以管理某一类型的所有事件

为什么:一般来说,dom需要有事件处理程序,我们都会直接给它设事件处理程序就好了,那如果是很多的dom需要添加事件处理呢?比如我们有100个li,每个li都有相同的click点击事件,可能我们会用for循环的方法,来遍历所有的li,然后给它们添加事件,那这么做会存在什么影响呢?在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能;

每个函数都是一个对象,是对象就会占用内存,对象越多,内存占用率就越大,自然性能就越差了(内存不够用,是硬伤,哈哈),比如上面的100个li,就要占用100个内存空间,如果是1000个,10000个呢,那只能说呵呵了,如果用事件委托,那么我们就可以只对它的父级(如果只有一个父级)这一个对象进行操作,这样我们就需要一个内存空间就够了,是不是省了很多,自然性能就会更好。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<ul id="ul1">
    <li>111</li>
    <li>222</li>
    <li>333</li>
    <li>444</li>
</ul>
<script>    //无事件代理    window.onload = function(){        var oUl = document.getElementById("ul1");        var aLi = oUl.getElementsByTagName(&#39;li&#39;);        for(var i=0;i<aLi.length;i++){            aLi[i].onclick = function(){                alert(123);
            }
        }
    };    //事件代理    window.onload = function(){        var oUl = document.getElementById("ul1");        oUl.onclick = function(ev){            var ev = ev || window.event;            var target = ev.target || ev.srcElement;            if(target.nodeName.toLowerCase() == &#39;li&#39;){                alert(123);                alert(target.innerHTML);
            }
        }
    }
</script>
</body>
</html>
Nach dem Login kopieren

相关推荐:

js中DOM事件绑定详解

JS中DOM如何操作

js中DOM知识点分享

Das obige ist der detaillierte Inhalt vonDetaillierte Erklärung des DOM-Ereignisflusses in js. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage