专栏名称: niayyy
学生
今天看啥  ›  专栏  ›  niayyy

浏览器DOM事件机制简介

niayyy  · 掘金  ·  · 2020-02-17 07:39

文章预览

阅读 19

浏览器DOM事件机制简介

在项目开发中经常会有许多 DOM 事件操作,对键盘敲击事件,鼠标点击事件,因此浏览器中的 DOM 事件的触发机制需要了解


DOM 级别一共分为 DOM 0 级,DOM 1 级,DOM 2 级,DOM 3 级,4 个级别

但是由于 DOM 1 级中没有 DOM 事件

因此DOM 事件分为3种级别

DOM 事件

DOM 0级(非 W3C 标准)

分为两种

  1. 在 HTML 标签中定义的事件
  2. element.on事件名 = function() { }
// <div onclick="test(this)"></div>

function test(e) {
	console.log(this)
}

// 或者
element.onclick = function() {}
复制代码

DOM 0 级事件有 2 种方法进行绑定,但只能绑定单个事件,该事件在目标阶段执行

DOM 1级事件

DOM级别1于1998年10月1日成为W3C标准。1 级DOM标准中并没有定义事件相关的内容,所以没有 1 级DOM事件模型。

DOM 2级事件

DOM 2 级事件弥补了不能多事件绑定的缺点,多个事件按照绑定先后顺序触发

element.addEventListener(EventName, callBack, useCapture)
// userCapture 默认为 false,在冒泡阶段监听事件,设为 true 可在捕获阶段监听事件
// 一般用 false,为了兼容 IE

element.removeEventListener(EventName, callback, false) // 移除事件
// IE9 之前
element.attachEvent()

element.detachEvent()
复制代码

useCapture 其他可设置属性 capture: 是否在捕获阶段触发监听 默认 false,一般使用默认,为了兼容 IE once: 设为 true 则监听函数是否触发一次 passive: 设为 true 则监听函数中不能调用 e.preventDefault() 方法,否则输出警告

element.addEventListener('click', function() {
    console.log('welcome')
}, { once: true }) // 只会在第一次点击时打印 welcome
复制代码

DOM 3级事件

包括以下:

  • UI 事件 load, scoll
  • 焦点事件 blur, focus
  • 鼠标事件 mousedown, mouseup
  • 滑轮事件 mousewheel
  • 文本事件 textInput
  • 键盘事件 keydown
  • 触摸事件 touch
  • 拖拽事件 dragstart, dragend, dragover, dragenter, dragleave, drop
  • 合成事件 compositionstart
  • 变动事件 DOMsubtreeModified

DOM 事件模型

DOM 事件模型

DOM 事件在触发后经历 3 个阶段,分别为:

  1. 捕获(capture)阶段,事件从 window 对象传播到目标阶段

    当用 addEventListener 监听事件时的最后一个参数为 true 时可以在捕获阶段触发事件

  2. 目标(target)阶段,目标节点处理事件

    用 DOM 0 级事件的函数在此时执行

  3. 冒泡(bubble)阶段,事件从目标节点传播到 window 对象

    addEventListener 事件默认在此阶段触发

    <div id="box">
        <a id="sub">事件冒泡</a>
    </div>
    
    <script>
    const box = document.getElementById('box'),
    const sub = document.getElementById('sub')
    
    box.addEventListener('click', function() {
        console.log('捕获阶段触发.box')
    }, true);
    sub.addEventListener('click', function() {
        console.log('捕获阶段触发.sub')
    }, true);
    sub.onClick = function() {
        console.log('目标阶段触发')
    }
    sub.addEventListener('click', function() {
        console.log('事件冒泡触发.sub')
    }, false);
    box.addEventListener('click', function() {
        console.log('事件冒泡触发.box')
    }, false);
    
    const event = new Event('click')
    sub.dispatchEvent(event) // 触发点击事件
    </script>
    // 捕获阶段触发.box
    // 捕获阶段触发.sub
    // 目标表阶段触发
    // 事件冒泡触发.sub
    // 事件冒泡触发.box
    复制代码

DOM 实现事件委托

为什么使用事件委托?

  1. 当有大量相同子节点触发同一个事件,可在冒泡阶段动态监听事件,防止创建过多函数,占用过多内存
  2. 对子节点删除时,不用考虑其他,降低耦合
  3. 绑定更少元素,降低操作 DOM 次数
<ul>
	<li></li>
	<li></li>
	<li></li>
	......
	<li></li>
</ul>
<script>
document.querySelector('ul').addEventListener('click', function(e) {
	console..log('click is:' + e.target.value)
    let value = e.target.value
    switch value {
        case 0:
            ...
            return ;
        case 1:
            ... 
            return ;
       ......
    }
})
</script>
复制代码

event 常用对象

  • event.preventDefault()

    阻止默认事件触发,比如 <a> 的跳转,表单的提交按钮

    // <a href="https://www.google.cn">link</a>
    a.onclick = function() {
    	return false
    }
    
    a.onclick = function(e) {
    	e = e || window.event
    	e.preventDefault();
    }
    <a href="javascript:;"></a> // 该方法一样可以阻止 <a> 默认事件触发
    复制代码
  • event.stopPropagation()

    阻止事件冒泡

    <div id="box">
        <a id="sub">事件冒泡</a>
    </div>
    
    <script>
    const box = document.getElementById('box'),
    const sub = document.getElementById('sub')
    sub.addEventListener('click', function(event) {
        console.log('111')
        e.stopPropagation()
    }, false);
    sub.addEventListener('click', function(event) {
        console.log('222')
    }, false);
    box.addEventListener('click', function(event) {
        console.log('父类上的监听事件')
    }, false);
    </script>
    
    // 111
    // 222
    复制代码
  • event.stopImmediatePropagation()

    立即阻止事件冒泡,也阻止同级的其他监听

    <div id="box">
        <a id="sub">事件冒泡</a>
    </div>
    
    <script>
    const box = document.getElementById('box'),
    const sub = document.getElementById('child')
    sub.addEventListener('click', function(event) {
        console.log('111')
        e.stopImmediatePropagation()
    }, false);
    sub.addEventListener('click', function(event) {
        console.log('222')
    }, false);
    box.addEventListener('click', function(event) {
        console.log('父类上的监听事件')
    }, false);
    </script>
    
    // 111
    复制代码
  • e.target

    事件触发的元素(真正的事件发出者)

  • e.currentTarget

    事件绑定的元素(事件监听者)

element.dispatchEvent(event)

手动触发事件

el.addEventListener('click', function() {
    console.log('dispatch 触发')
}, false)
let event = new Event('click')
el.dispatchEvent(event)

// dispatch 触发
复制代码
………………………………

原文地址:访问原文地址
快照地址: 访问文章快照
总结与预览地址:访问总结与预览