谈谈 文档对象模型-DOM
DOM 事件
-
1,DOM 事件级别
分为3个级别
DOM0级 对应 DOM0 级事件处理
DOM2级 对应 DOM1 级事件处理
DOM3级 对应 DOM2 级事件处理-
DOM0
DOM0 事件绑定,是最原始的事件绑定,直接在 HTML 元素上写事件 onclick ,赋值为一个函数即可。
缺点是 HTML 与 JS 强耦合,修改函数名,那么需要找到当前对应的 HTML 元素,并且更改函数名。也不能同时绑定多个函数。如何实现低耦合?
通过get HTML 元素的 id获得元素,然后直接对元素设置 onclick 属性优点是不需要操作 DOM 来完成事件的绑定。不存在兼容性问题
清理 DOM 事件时,只需要给该事件赋值为 null
-
DOM2
DOM2 级事件在 DOM0 级事件的基础上弥补了一个无法绑定多个处理函数的缺点,允许给一个处理程序添加多个处理函数。
addeventlistener,removeeventlistener
IE8 以下版本不支持上面两个方法,要使用 attachevent 和 detachevent优点:可以绑定多个处理函数,顺序执行。
缺点:有兼容性问题
三个参数第一个事件名,第二个是处理函数,第三个是布尔值,true 表示在捕获阶段调用,false 时表示在冒泡阶段调用。
-
DOM3
DOM3 级事件在 DOM2 事件的基础上添加了更多的事件类型:
UI 事件
焦点事件
鼠标事件
滚轮事件
文本事件
键盘事件
合成事件
同时 DOM3 级事件也允许使用者自定义一些事件。
举个栗子var eve = new Event('custome') ev.addEventListem('custom',function () { console.log('custome') }) ev.dispatchEvent(eve)
-
-
2,DOM 事件流
为什么有事件流?
假如我们在一个 button 上注册了一个 click 事件,又在其父元素DIV 上注册了一个 click 事件,那么当我们点击 button 的时候,是先触发父元素 div 的事件还是 button 上的事件呢,这就需要一种约定来规范事件的执行顺序,这就是事件执行的流程。 -
3,DOM 事件模型
-
捕获
事件从 window 对象自上而下向目标节点传播的阶段
子元素和父元素上同时绑定了 click 事件,点击时会先执行父元素的处理函数,然后执行子元素的处理函数
-
目标阶段
真正目标节点正在处理事件的阶段
-
冒泡
事件从目标节点自下而上向 window 对象传播的阶段
子元素和父元素上同时绑定了 click 事件,点击时会先执行子元素的处理函数,然后执行父元素的处理函数
-
-
4,DOM 事件代理(事件委托)
由于事件会在冒泡阶段向上传播到父节点,因此可以把子节点的监听函数定义在父节点上,油父节点的监听函数统一处理多个子元素的事件,这种方法叫做事件委托。
应用场景:有一个列表,列表中有大量的列表项,我们需要在点击每个列表项的时候响应一个事件。
此场景为什么要使用事件委托?
1,函数是对象,会占用内存,内存中对象越多,浏览器性能越差,如果给每个列表项都加一个事件,对于内存消耗是非常大的,效率上也要消耗很多性能。
2,注册的事件越多,导致 DOM 元素访问次数越多,会延迟页面交互就绪事件
3,动态添加或者删除子元素的时候不用考虑增加或者删除绑定事件。
举个栗子:
<ul id="list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> <script> // 给父层元素绑定事件 document.getElementById('list').addEventListener('click', function (e) { // 兼容性处理 var event = e || window.event; var target = event.target || event.srcElement; // 判断是否匹配目标元素 if (target.nodeName.toLocaleLowerCase() === 'li') { console.log('the content is: ', target.innerHTML); } }); </script>
-
5,event 对象常见的方法和属性
-
1,event.preventDefault()
如果调用这个方法,默认事件行为将不再触发,如表单一点击提交按钮就刷新页面,a 标签默认页面跳转或者是锚点定位等
举个栗子:
<a id="test" href="http://www.google.com">链接</a> <script> test.onclick = function(e){ e = e || window.event; e.preventDefault(); } </script>
除此以外还有两种方法可以阻止 A 标签跳转
方法 1:
<a href="javascript:;">链接</a>
方法 2:
<a id="test" href="http://www.google.com">链接</a> <script> test.onclick = function(e){ e = e || window.event; return false; } </script>
-
2,event.stopPropagation() & event.stopImmediatePropagation()
event.stopPropagation() 方法阻止事件冒泡到父元素,阻止任何父事件处理程序被执行。
event.stopImmediatePropagation() 方法除了可以阻止向父元素冒泡以外,还可以阻止相同事件类型的其他监听器被触发。
举个栗子:
<button id="btn">点我试试</button> <script> const btn = document.querySelector('#btn'); btn.addEventListener('click', event => { console.log('btn click 1'); event.stopImmediatePropagation(); }); btn.addEventListener('click', event => { console.log('btn click 2'); }); document.body.addEventListener('click', () => { console.log('body click'); }); </script>
上面只会打印出 btn click1
-
4,event.target & event.currentTarget
event.target指向引起触发事件的元素,而 event.currentTarget 则指向添加监听事件的对象
-