DOM事件模型

事件

参考:

W3C链接

了解DOM 事件模型

DOM 事件详解

事件捕获、事件冒泡以及事件代理

原生JavaScript和Vue、小程序都是如何阻止事件冒泡的?


 

DOM事件级别


 

1 事件流

事件流描述的是从页面中接受事件的顺序。

1.1 事件冒泡

IE 的事件流叫事件冒泡,即事件开始时由最具体的元素接受,然后逐级向上传播到较为不具体的节点(文档),Chrome,Firefox和Safari会将事件一直冒泡到 window 对象。

1.2 事件捕获

Netscape Communicator 团队提出的另一种事件流叫做事件捕获。事件捕获的思想是不太具体的节点应该更早接受到事件,而最具体的节点应该最后接收到事件。事件捕获的用以在于事件到达预定目标之前捕获它。一般从document对象开始传播,用的较少。

1.3 DOM事件流

Graphical representation of an event dispatched in a DOM tree using the DOM event flow

上图是W3C标准的DOM事件流模型图。

“DOM2级事件” 规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段。


 

2 事件处理程序

前面说的是事件,事件就是用户或浏览器自身执行的某种动作。如:click是事件的名字,事件处理程序就是onclick。为事件指定处理程序的方式有好几种

2.1 HTML 事件处理程序

其实就是,HTML 的on属性

<button onclick="doxxx()">点击</button>

使用这个方法指定的监听代码只会在冒泡阶段触发。

2.2 DOM0 级事件处理程序,缺点:无法设置多个事件处理函数

元素节点的事件属性。

let btn = document.getElementById("myBtn:);
btn.onclick = function () {
    alert("Clickes")      
}

如果想删除只需:btn.onclick = null;  // 删除事件处理程序

2.3 DOM2 级事件处理程序,可以为事件设置多个事件处理函数,可以通过第三个参数 ( useCapture ) 设置在什么阶段执行事件处理函数,默认是 false, 即在事件冒泡阶段执行事件处理函数。

DOM2级事件定义了两个方法,用于处理指定 和 删除事件处理程序的操作:addEventListener()removeEventListener()

所有DOM节点中都包含这两种方法。并且都接受三个参数:要处理的事件名作为事件处理程序的函数一个布尔值(默认false表冒泡)

(1)EventTarget.addEventListener()

function print() {
  console.log('Print Hello world');
}

var btn = document.getElementById('btn');
btn.addEventListener('click', print, false);

上面代码的意思就是,节点id为btn的元素,使用addEventListener方法绑定click事件,点击的时候会监听函数print会发生。另外,因为useCapture设置为false,所以该函数只在冒泡阶段触发
当我们需要添加多个不同的监听函数,使用addEventListener非常棒,遵从先添加先触发原则,而且不小心在同一个事件重复添加了同一个函数,它还会自动移除,该函数只会执行一次。

(2)EventTarget.removeEventListener()
顾名思义,用来移除addEventListener方法添加的事件监听函数。
它的参数和addEventListener方法一致,而且写的时候要一一对应。要做到三同,一是在同一个元素节点,二是同一个监听函数,三是第三个参数要一致。

2.4 IE 事件处理程序

(1)事件绑定监听函数:attachEvent(eventType, listener)
(2)事件移除监听函数:detachEvent(eventType, listener)


 

3 事件对象

3.1 DOM 中的事件对象

事件发生的时候,会将一个 event 对象传入到事件处理程序中,从而可以使用对象的属性和方法。我随意列出几个。
bubbles:返回一个布尔值,表示当前事件是否会冒泡。该属性为只读属性
cancelable:返回一个布尔值,表示事件是否可以取消。该属性为只读属性
currentTarget:事件处理程序当前正在处理事件的那个元素
preventDefault():取消事件的默认行为。如果 cancelable 是true,则可以使用这个方法
stopPropagation():取消事件的进一步捕获或冒泡。如果 bubbles为 true,则可以使用这个方法。
事件处理程序使用DOM0 级或是 DOM2 级,都会传入 event 对象,这个我们不用care。
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
      console.log(event.type);    //"click"
  };
btn.addEventListener("click", function(event){
      console.log(event.type);    //"click"
  }, false);
<button onclick="console.log(event.type)()">点击</button>

3.2 IE中的事件对象

与访问DOM中的event对象不同,要访问IE中的event对象有几种不同的方式,取决于指定事件处理程序的方法。

(1) HTML 事件处理程序

<button onclick="console.log(event.type)()">点击</button>

(2) DOM0 级事件处理程序

let btn = document.getElementById("btn");
btn.onclick = function(){
 var event = window.event;
 console.log(event.type);     //"click"
};

(3) DOM2 级事件处理程序

let btn = document.getElementById("btn");
btn.attachEvent("onclick", function(event){
 console.log(event.type);         //"click"
});

 

4 事件类型(DMO3 级事件规定了以下几类事件)

DOM3 级事件是在 DOM2 级事件的基础上添加了更多的事件类型,允许自定义事件。

  • UI事件,当用户与页面上的元素交互时触发,如:load、scroll
  • 焦点事件,当元素获得或失去焦点时触发,如:blur、focus
  • 鼠标事件,当用户通过鼠标在页面执行操作时触发如:dbclick、mouseup
  • 滚轮事件,当使用鼠标滚轮或类似设备时触发,如:mousewheel
  • 文本事件,当在文档中输入文本时触发,如:textInput
  • 键盘事件,当用户通过键盘在页面上执行操作时触发,如:keydown、keypress
  • 合成事件,当为IME(输入法编辑器)输入字符时触发,如:compositionstart
  • 变动事件,当底层DOM结构发生变化时触发,如:DOMsubtreeModified

如何阻止冒泡

 

例子:

<div onclick="alert('最外层')">
    <div onclick="alert('中间层')">
        <a id="ahref" href="http://www.javanx.cn" onclick="alert('最里层')">点击我</a>
    </div>
</div>

点击:点击我 --》最里层 --》中间层 --》最外层 --》然后转跳链接。这就是冒泡。

1.JavaScript 中

event.stopPropagation()  // propagation: 传播
$(function() {
    $("#ahref").click(function(event) {
        event.stopPropagation();
    });
});

点击:点击我 --》 最里层 --》转跳链接  事件处理过程中,阻止了事件冒泡,但不会阻击默认行为(执行了超链接的跳转)

return false

$(function() {
    $("#ahref").click(function(event) {
        return false;
    });
});

点击:点击我 --》 最里层 --》但不会转跳链接  事件处理过程中,阻止了事件冒泡,也阻止了默认行为(没有执行超链接的跳转)

event.preventDefault()

$(function() {
    $("#ahref").click(function(event) {
        event.preventDefault()  
    });
});

 点击:最里层 --》中间层 --》最外层,但最后没有转跳  不能阻止事件冒泡,但阻止了默认行为。

2.Vue 解决事件冒泡

Vue.js 提供了事件修饰符,我们只需要添加 click.stop 即可预防事件冒泡

<div @click="cancelSelect">
    <div class="picker_alert" @click.stop>
        <div class="ofh">
            <span @click="toRoomManagement">编辑</span>
            <span @click="confirmRoom">确定</span>
        </div>
    </div>
</div>

Vue修饰符:.stop, .prevent, .capture, .self, .once

<!-- 阻止单击事件冒泡 -->
<a v-on:click.stop="doThis"></a>
 
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>
 
<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>
 
<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>
 
<!-- 添加事件侦听器时使用事件捕获模式 -->
<div v-on:click.capture="doThis">...</div>
 
<!-- 只当事件在该元素本身(比如不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>

提示:使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。
因此,用 @click.prevent.self 会阻止所有的点击,而 @click.self.prevent 只会阻止元素上的点击。

 

 

 

posted @ 2020-08-26 15:11  Mock777  阅读(253)  评论(0编辑  收藏  举报