ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[TOC] DOM是和HTML文档关联的东西,其实很js没有本质的关系,只是js很多时候用来处理dom而已。 此外为了方便js操作dom,有一些框架库可以选用,比如jquery。 # DOM0级事件处理方式: 通过javascript制定事件处理程序的传统方式。就是将一个函数赋值给一个事件处理属性。第四代web浏览器出现,至今为所有浏览器所支持。优点,简单且具有跨浏览器的优势。 例: ~~~ var btn = document.getElementById("btn"); btn.onclick = function(){ alert(this.id);//this指定当前元素btn } ~~~ 或者 `<input onclick="alert(1)" />` 删除DOM0事件处理程序,只要将对应事件属性置为`null`即可。 ~~~ btn.onclick = null; ~~~ 缺点:一个事件处理程序只能对应一个处理函数。 * DOM2 是通过`addEventListener`绑定的事件,还有 IE 下的 DOM2 事件通过`attachEvent`绑定; * DOM3 是一些新的事件,区别 DOM3 和 DOM2 的方法我感觉是 DOM3 事件有分大小写的,DOM2 没有; # 事件流 ![](https://box.kancloud.cn/315d2fca5b0dbbc55e451294c31a1587_394x357.png) IE的事件流是冒泡, 从里面往上面冒, netscape是从外部元素往内部元素捕获; 而**DOM2级的事件规定了事件流包含三个阶段**包括: * 1:事件捕获 * 2:处于目标阶段 * 3:事件冒泡阶段 (IE8以及更早版本不支持DOM事件流); ## 捕获和冒泡 ~~~ <div id="div1"> <div id="div2"></div> </div> <script> let div1 = document.getElementById('div1'); let div2 = document.getElementById('div2'); div1.onClick = function(){ alert('1') } div2.onClick = function(){ alert('2'); } </script> ~~~ > 当点击`div2`时,会弹出两个弹出框。在`ie8/9/10`、`chrome`浏览器,会先弹出”2” 再弹出 “1”,这就是事件冒泡:事件从最底层的节点向上冒泡传播。 > 绑定在被点击元素的多个事件是按照代码顺序发生,其他元素通过冒泡或者捕获 “感知” 的事件,按照 W3C 的标准,先发生捕获事件,后发生冒泡事件。所有事件的顺序是:其他元素捕获阶段事件 -> 本元素代码顺序事件 -> 其他元素冒泡阶段事件 。 > `addEventListener`的第三个参数(`useCapture`参数默认值为`false`)决定把事件发生时机是在捕获阶段(`true`)还是冒泡阶段 (`false`)。 # DOM2级事件处理方式 DOM2级事件处理方式指定了,添加事件处理程序和删除事件处理程序的方法。分别是: ``` addEventListener(eventName,func,isPuhuo); removeEventListener(eventName,func,isPuhuo); ``` 例如: ``` var btn = document.getElementById("btn"); handler = function(){ …… } addEventListener("click",handler,false/true); removeEventListener("click",handler,false/true); ``` 参数分别是,事件处理属性名称,处理函数,是否在捕获时执行事件处理函数。 注: 1. `eventName`的值均不含 `on`,例如注册鼠标点击事件 eventName 为 `click`; 2. 处理函数中的 `this` 依然指的是指当前dom元素( [addEventListener 回调中的 this 指向](https://www.jianshu.com/p/4943571dcac5)); 3. 通过 `addEventListener` 添加的事件处理程序,只能通过 `removeEventListener` 来删除,也就是说通过 `addEventListener` 添加的匿名函数将无法被删除。 ``` var btn = document.getElementById("myBtn"); btn.addEventListener("click", function () { alert(this.id); }, false); btn.removeEventListener("click", function () { //无效! alert(this.id); }, false); ``` ## 事件对象 ![](https://img.kancloud.cn/4c/cb/4ccb9a70d4b97f028d05769701a7f067_728x893.png) # IE中的DOM2级事件处理 IE 中的 DOM2 级事件处理使用了 `attachEvent` 和 `detachEvent` 来实现。这俩个方法接受俩个相同的参数,事件处理名称和事件处理函数。IE8 级更早版本只支持冒泡型事件,所以attachEvent添加的事件都会被添加到冒泡阶段。 例如: ``` var btn = document.getElementById("btn"); btn.attachEvent("onclick",function(){ alert(this);//此处this是window }); ``` 注意;通过 `attachEvent` 添加的事件第一个参数是 `onclick` 而非标准事件中的 `click` 。在使用 `attachEvent` 方法和 DOM0 级事件处理程序的主要区别在于事件处理程序的作用域。采用DOM0级处理方式,事件处理程序会在其所属元素的作用域内运行。使用 `attachEvent` ,事件处理程序会在全局作用域内运行,因此 `this` 等于 `window` 。 ## 怎么移除匿名函数? 啊哈哈哈,我知道问题出在哪了,也知道 `arguments.callee`(严格模式禁止) 到底是什么了!原来在函数内,`arguments.callee` 是指本函数,也就是函数自身,所以以下会在控制台输出函数 `aa`(toString 后也就是函数的代码)。 ``` (function aa() { console.log(arguments.callee); }()); ``` 而我要的函数不是这个,而是绑定到 `click` 的函数,所以代码应该改成这样: ``` var i = 0; function init() { aabtn.addEventListener("click", function(e) { aa(arguments.callee); }); } function aa(fun) { tex.innerHTML = i++; aabtn.removeEventListener("click", fun); } ``` >参考:https://segmentfault.com/q/1010000002462675 ### 3、DOM3事件 DOM浏览器中可能发生的事件有很多种,不同事件类型具有不同的信息,DOM3级事件规定了一下几种事件: UI事件,当用户与页面上的元素交互时触发; 焦点事件,当元素获得或者失去焦点时触发; 鼠标事件,当用户通过鼠标在页面上执行操作时触发; 滚轮事件,当使用鼠标滚轮(或类似设备)时触发; 文本事件,当在文档中,输入文本时触发; 键盘事件,当用户通过键盘在页面上执行操作时触发; 合成事件,当为IME(Input Method Editor,输入法编辑器)输入字符时触发; 变动事件,当底层Dom结构发生变化时触发; DOM3级事件模块在DOM2级事件的基础上重新定义了这些事件,也添加了一些新事件。包括IE9在内的主流浏览器都支持DOM2级事件,IE9也支持DOM3级事件。 DOM中的事件模拟(自定义事件): DOM3级还定义了自定义事件,自定义事件不是由DOM原生触发的,它的目的是让开发人员创建自己的事件。 事件对象`event`下的属性和方法: ``` 因为各个浏览器的事件对象不一样, 把主要的时间对象的属性和方法列出来; bubble : 表明事件是否冒泡 cancelable : 表明是否可以取消冒泡 currentTarget : 当前时间程序正在处理的元素, 和this一样的; defaultPrevented: false ,如果调用了preventDefualt这个就为真了; detail: 与事件有关的信息(滚动事件等等) eventPhase: 如果值为1表示处于捕获阶段, 值为2表示处于目标阶段,值为三表示在冒泡阶段 target || srcElement: 事件的目标 trusted: 为ture是浏览器生成的,为false是开发人员创建的(DOM3) type : 事件的类型 view : 与元素关联的window, 我们可能跨iframe; preventDefault() 取消默认事件; stopPropagation() 取消冒泡或者捕获; stopImmediatePropagation() (DOM3)阻止任何事件的运行; //stopImmediatePropagation阻止 绑定在事件触发元素的 其他同类事件的callback的运行 IE下的事件对象是在window下的,而标准应该作为一个参数, 传为函数第一个参数; IE的事件对象定义的属性跟标准的不同,如: cancelBubble 默认为false, 如果为true就是取消事件冒泡; returnValue 默认是true,如果为false就取消默认事件; srcElement, 这个指的是target, Firefox下的也是srcElement; ``` # 参考 [史上最详细的JavaScript事件使用指南](http://www.admin10000.com/document/6293.html) [JavaScript 和事件](https://yujiangshui.com/javascript-event/) 小胡子的 [[解惑]JavaScript事件机制](http://www.cnblogs.com/hustskyking/p/problem-javascript-event.html) 叶小钗的[【探讨】javascript事件机制底层实现原理](http://www.cnblogs.com/yexiaochai/p/3477715.html)