#再读DOM# (1)DOM 事件模型

    科技2022-07-16  99

    概念 事件:事件是用户或者浏览器自己执行的某种动作,是文档或者浏览器发生的一些交互瞬间 事件流:当一个事件被触发时,一个event对象将被创建并顺序的传递给事件监听者们。事件传递的顺序称为事件流。 事件处理程序:响应事件的函数。如click是事件名称,加上"on"开头,事件处理程序是onclick 事件在子元素和父元素之间的传播分为3个阶段:(1)捕获阶段:事件从window对象自上而下向目标节点传播的阶段;(2)目标阶段:真正的目标节点正在处理事件的阶段;(3)冒泡阶段:事件从目标节点自下而上向window对象传播的阶段。 事件处理程序分类 DOM0 级事件处理程序:元素节点的事件属性。在当前元素事件行为的冒泡阶段(或者目标阶段)执行的。只能绑定一个,后面的会覆盖前面的。 var btn = document.getElementById('btn'); btn.onclick = function () { console.log('被点击了!'); }; //增加 btn.onclick = null; // 删除事件处理程序

    DOM2 级事件处理程序:addEventListener()和removeEventListener()。可以同一个元素绑定多个事件。 eventType ————> 事件名称,大小写敏感 listener ————> 监听函数 useCapture ————> 可选参数,默认false,表示监听函数只在冒泡阶段被触发。

    target.addEventListener(eventType, listener[, useCapture]);

    DOM 3级事件:在DOM 2级事件的基础上添加了更多的事件类型。 IE9以下的IE浏览器不支持 addEventListener()和removeEventListener(),使用 attachEvent()与detachEvent() 代替,因为IE9以下是不支持事件捕获的,所以也没有第三个参数,第一个事件名称前要加on。

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

    事件模型分类 W3C同时支持捕获和冒泡。事件在两个阶段都可以执行,程序员可以根据需求自行设定。 默认值为false,即在冒泡阶段执行事件函数。 捕获 捕获是从上到下,事件先从window对象,然后再到document(对象),然后是html标签(通过document.documentElement获取html标签),然后是body标签(通过document.body获取body标签),然后按照普通的html结构一层一层往下传,最后到达目标元素。 事件冒泡是IE 的事件流 冒泡 冒泡流程是捕获的逆流程。 事件捕获是Netscape浏览器开发团队提出的

    事件委托 优点: (1)减少内存消耗,提高性能(不给每个子元素单独绑定一个事件,而只在父元素上绑定一个事件,减少了占用的内存); (2)动态绑定事件(在元素会发生变变化甚至还未创建时,可以先将事件创建好) 由于事件会在冒泡阶段向上传播到祖先节点(爸爸节点、爷爷节点),因此可以把子节点的监听函数定义在祖祖先节点上,由祖先节点的监听函数统一处理多个子元素的事件。这种方法叫做事件的代理(delegation)。

    // 给父层元素绑定事件 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); } }); // 自己封装委托函数 on('click','#div1','button',()=>{ console.log('button被点击了') }) function on(eventType,element,selector,fn){ if(!(element instanceof Element)){ element=document.querySelector(element) } element.addEventlistener(eventType,(e)=>{ const t=e.target if(t.matches(selector)){ fn(e) } }) } 事件应用 阻止默认:调用这个方法,默认事件行为将不再触发。 cancelable:true可以取消/不可取消。有些默认事件是无法取消的 event. preventDefault()

    阻止a链接默认跳转的方法:

    //方法一: <a href="javascript:;">链接</a> //方法二: <a id="test" href="http://www.cnblogs.com">链接</a> <script> test.onclick = function(e){ e = e || window.event; return false; } </script> //方法三: <a id="test" href="http://www.cnblogs.com">链接</a> <script> test.onclick = function(e){ e = e || window.event; e.preventDefault(); } </script>

    阻止冒泡:event.stopPropagation() 方法阻止事件冒泡到父元素,阻止任何父事件处理程序被执行。 bubbles:true可以阻止冒泡/false不能阻止冒泡。几乎所有的事件都可以阻止冒泡 stopImmediatePropagation 既能阻止事件向父元素冒泡,也能阻止元素同事件类型的其它监听器被触发。而 stopPropagation 只能实现前者的效果。

    <body> <button id="btn">click me to stop propagation</button> </body> ...... 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'); }); // btn click 1 // 使用 stopImmediatePropagation后,点击按钮时,不仅body绑定事件不会触发,与此同时按钮的另一个点击事件也不触发。 事件对象event.target & event.currentTarget event.target指向引起触发事件的元素,而event.currentTarget则是事件绑定的元素,只有被点击的那个目标元素的event.target才会等于event.currentTarget。也就是说,event.currentTarget始终是监听事件者,而event.target是事件的真正发出者。 如:事件监听者为div,但是点击div中的span标签时,可以冒泡触发div的事件处理程序。此时event.target是span,event.currentTarget是div。

    参考: https://developer.mozilla.org/zh-CN/docs/Web/API/Document_Object_Model/Events https://juejin.im/post/6844903731079675917 https://juejin.im/post/6844903850323755021

    Processed: 0.010, SQL: 8