js原生事件

参考文章一

一、事件是什么


事件就是文档或浏览器窗口中发生的一些特定的交互瞬间,是可以被 JavaScript 侦测到的行为  

二、DOM事件流的三个阶段


  • 事件捕获阶段:实际目标(
    )在捕获阶段不会接收事件。也就是在捕获阶段,事件从document到再到就停止了。
  • 处于目标阶段 :事件在
    上发生并处理。但是事件处理会被看成是冒泡阶段的一部分。
  • 事件冒泡阶段 :事件又传播回文档。

js原生事件_第1张图片

三、两种事件流模型


(一)事件冒泡(IE的事件流)

事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为
不具体的节点。  

js原生事件_第2张图片

(二)事件捕获(Net Communicator的事件流)

事件捕获的思想是不太具体的节点应该更早的接收到事件,而具体的节点应该最后接收到事件   

js原生事件_第3张图片

由于老版本浏览器不支持,很少有人使用事件捕获。建议使用事件冒泡。

四、事件绑定——事件处理程序


(一)在DOM中直接绑定事件

我们可以在DOM元素上绑定onclick、onmouseover、onmouseout、onmousedown、onmouseup 
、ondblclick、onkeydown、onkeypress、onkeyup等。
<input type="button" value="click me" onclick="hello()">

<script>
function hello(){
    alert("hello world!");
}
script>

(二)在JavaScript代码中绑定事件

将一个函数赋值给一个事件处理程序属性,在元素的作用域中运行,程序中的this引用当前元素
var btn = document.getElementById("myBtn");
btn.onclick = function(){
    alert(this.id); //"myBtn"
}

(三)使用事件监听绑定事件

绑定事件的另一种方法是用 addEventListener() 或 attachEvent() 来绑定事件监听函数。

五、事件监听


(一)“DOM2级事件”定义了两个方法,处理和删除addEventListener()和removeEventListener()

document.addEventListener(event, function, useCapture);  
document.removeEventListener(event, function, useCapture)

两个方法的参数相同
js原生事件_第4张图片

document.addEventListener("click", myFunction);

function myFunction() {
    document.getElementById("demo").innerHTML = "Hello World";
}

可以给元素添加多个事件,会按照添加顺序触发

document.addEventListener("click", myFunction);
document.addEventListener("click", someOtherFunction);
// 在文档中添加事件句柄
document.addEventListener("mousemove", myFunction);

// 移除文档中的事件句柄
document.removeEventListener("mousemove", myFunction);

(二)IE事件处理程序的两个方法——attachEvent()和detachEvent()

事件处理程序会在全局作用域运行,此时的this等于window,和“DOM2级事件”的不同点
element.attachEvent(event, function)
element.detachEvent(event, function)
  • event:(必需)事件类型。需加“on“,例如:onclick。
  • function:(必需)指定要事件触发时执行的函数。
<input type="button" value="click me" id="btn2">
<script>
document.getElementById("btn2").attachEvent("onclick",hello);
function hello(){
    alert("hello world!");
}
script>

(三)事件监听的优点

  • 可以绑定多个事件。
  • 可以解除相应的绑定

六、事件委托


事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
使用事件委托,只需在DOM树中尽量最高的层次上添加一个事件处理程序   

传统写法:

<ul id="list">
  <li id="item1" >item1li>
  <li id="item2" >item2li>
  <li id="item3" >item3li>
ul>

<script>
var item1 = document.getElementById("item1");
var item2 = document.getElementById("item2");
var item3 = document.getElementById("item3");

item1.onclick = function(){
    alert("hello item1");
}
item2.onclick = function(){
    alert("hello item2");
}
item3.onclick = function(){
    alert("hello item3");
}
script>

事件委托的写法:

<ul id="list">
  <li id="item1" >item1li>
  <li id="item2" >item2li>
  <li id="item3" >item3li>
ul>

<script>
var item1 = document.getElementById("item1");
var item2 = document.getElementById("item2");
var item3 = document.getElementById("item3");

document.addEventListener("click",function(event){
    var target = event.target;
    if(target == item1){
        alert("hello item1");
    }else if(target == item2){
        alert("hello item2");
    }else if(target == item3){
        alert("hello item3");
    }
})
script>

事件委托的优点

  • 整个页面占用的内存更少,提高整体性能
  • 设置的事件处理程序所需时间更少,所需的DOM引用更少

七、事件对象(event)


参考这里
重点参考文章

在触发DOM上的某个事件时,会产生一个事件对象event,这个对象中包含所有与事件相关的信息  

(一)DOM中的事件对象

event.type属性表示事件类型,例如"click"

event的属性和方法如下:

js原生事件_第5张图片
方法:
这里写图片描述

(二)IE中的事件对象

在使用DOM0级方法添加事件处理程序时,event对象作为window对象的一个属性   
btn.onclick = function(){
    var event = window.event;
    alert("event.type");   //"click"
}

event的属性和方法如下:

js原生事件_第6张图片
补充:type属性表示被触发的事件的类型

八、阻止冒泡


(一)stopPropagation() 方法

该方法立即停止事件在DOM层次上的传播,即取消进一步的事件捕获或冒泡

(二)cancelBubble属性—–只能取消冒泡

window.event.cancelBubble = true;

九、取消事件的默认行为


(一)preventDefault()方法

只有cancelBubble属性设置为true的事件,才可以使用这个方法

event.preventDefault();

(二)returnValue属性

window.event.returnValue=false;

(三)js的return false

十、写一个通用的事件侦听器函数

markyun.Event = {
        // 页面加载完成后
        readyEvent : function(fn) {
            if (fn==null) {
                fn=document;
            }
            var oldonload = window.onload;
            if (typeof window.onload != 'function') {
                window.onload = fn;
            } else {
                window.onload = function() {
                    oldonload();
                    fn();
                };
            }
        },
        // 视能力分别使用dom0||dom2||IE方式 来绑定事件
        // 参数: 操作的元素,事件名称 ,事件处理程序
        addEvent : function(element, type, handler) {
            if (element.addEventListener) {
                //事件类型、需要执行的函数、是否捕捉
                element.addEventListener(type, handler, false);
            } else if (element.attachEvent) {
                element.attachEvent('on' + type, function() {
                    handler.call(element);
                });
            } else {
                element['on' + type] = handler;
            }
        },
        // 移除事件
        removeEvent : function(element, type, handler) {
            if (element.removeEventListener) {
                element.removeEventListener(type, handler, false);
            } else if (element.datachEvent) {
                element.detachEvent('on' + type, handler);
            } else {
                element['on' + type] = null;
            }
        },
        // 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)
        stopPropagation : function(ev) {
            if (ev.stopPropagation) {
                ev.stopPropagation();
            } else {
                ev.cancelBubble = true;
            }
        },
        // 取消事件的默认行为
        preventDefault : function(event) {
            if (event.preventDefault) {
                event.preventDefault();
            } else {
                event.returnValue = false;
            }
        },
        // 获取事件目标
        getTarget : function(event) {
            return event.target || event.srcElement;
        },
        // 获取event对象的引用,取到事件的所有信息,确保随时能使用event;
        getEvent : function(e) {
            var ev = e || window.event;
            if (!ev) {
                var c = this.getEvent.caller;
                while (c) {
                    ev = c.arguments[0];
                    if (ev && Event == ev.constructor) {
                        break;
                    }
                    c = c.caller;
                }
            }
            return ev;
        }
    };

十一、事件的执行顺序


参考文章,讲的很清楚

先看两个问题:

一个DOM元素绑定两个事件,一个冒泡,一个捕获,则事件会执行多少次,执行顺序如何。  
 事件捕获和冒泡,顺序,如果一个元素的冒泡事件定义在捕获之前会发生什么  

总结结论

绑定在被点击元素的事件是按照代码顺序发生,其他元素通过冒泡或者捕获“感知”的事件,按照W3C的标准,先发生捕获事件,后发生冒泡事件。所有事件的顺序是:其他元素捕获阶段事件 -> 本元素代码顺序事件 -> 其他元素冒泡阶段事件 。

执行次数:绑定了几个事件便执行几次。

当每个元素绑定的事件不同,有冒泡有捕获时

首先,无论是冒泡事件还是捕获事件,元素都会先执行捕获阶段。

从上往下,如有捕获事件,则执行;一直向下到目标元素后,从目标元素开始向上执行冒泡元素,即第三个参数为true表示捕获阶段调用事件处理程序,如果是false则是冒泡阶段调用事件处理程序。(在向上执行过程中,已经执行过的捕获事件不再执行,只执行冒泡事件。)

<div id='one'>
  <div id='two'>
    <div id='three'>
      <div id='four'>
      div>
    div>
  div>
div>
<script type='text/javascript'>
  var one=document.getElementById('one');
  var two=document.getElementById('two');
  var three=document.getElementById('three');
  var four=document.getElementById('four');
 one.addEventListener('click',function(){
        alert('one');
 },true);  //捕获
 two.addEventListener('click',function(){
        alert('two');
 },false); //冒泡
 three.addEventListener('click',function(){
        alert('three');
 },true);  //捕获
 four.addEventListener('click',function(){
        alert('four');
 },false); //冒泡
script>

从根元素向目标元素向下判断执行,和目标元素本身的事件类型没有关系,根元素捕获—–>目标元素——>冒泡到根元素

此时点击four元素,最终执行结果为:one three four two
点击three元素,执行结果为:one three two  

当一个元素绑定两个事件,一个冒泡,一个捕获

如果点击元素有两个事件,按代码的顺序执行,其他元素先捕获后冒泡
如果点击的是其他元素,则有两个事件的元素先捕获后冒泡,与代码顺序无关

one.addEventListener('click',function(){
alert('one');
},true);
two.addEventListener('click',function(){
alert('two,bubble');
},false);
two.addEventListener('click',function(){
alert('two,capture');
},true);
three.addEventListener('click',function(){
alert('three,bubble');
},true);
four.addEventListener('click',function(){
alert('four');
},true);
1、如果two为目标元素,目标元素的事情按顺序执行,而其他元素根据W3C的标准执行,即先捕获
后冒泡。
点击two执行结果:one(因为是two的父元素支持捕获事件所以先执行)  two,bubble 
 two,capture(顺序执行,注意逗号不是间隔,是输出内容。)
2、如果目标元素不是two,则two的两个事件按先捕获后冒泡触发执行,也就是跟前面讨论的执行
过程是一样的,只不过两个事件都绑定在同一个DOM元素上。
点击three执行结果:one two,capture three,bubble two,bubble

你可能感兴趣的:(JS)