给 DOM 节点绑定事件
推荐使用 addEventListener 函数
- 第一个参数:事件名称
- 第二个参数:事件处理函数(第一个参数为 event)
- 第三个参数:
- true 采用捕获法来处理事件
- false 【推荐】采用冒泡法来处理事件
let div1= document.getElementById('div1'); div1.addEventListener('click', function(event){ alert('div1_clicked!'); }, false);
event 参数的用途
- event.stopPropagation() 阻止事件传播(冒泡/捕获)
事件流(含事件冒泡,事件捕获)
https://blog.csdn.net/weixin_41192489/article/details/133140101
【必考】事件代理
借助其他元素来响应自身事件即事件代理。
应用范例:对于内容很多的列表,为了避免给每一个列表中的元素都绑定一个点击事件,仅在列表的容器元素上绑定点击事件,则当点击列表中的元素时,因事件冒泡机制,会触发容器元素的点击事件,再在该事件中,识别出点击的具体元素,并执行相应的处理。
// 列表内容很多的容器 const div3 = document.getElementById("div3"); // 点击列表中a标签的元素时,弹窗显示其内容 div3.addEventListener("click", (event) => { event.preventDefault(); let target = event.target; if (target.nodeName === "A") { alert(target.innerHTML); } });
【考题】写一个通用的事件绑定函数
/** * 通用的事件绑定函数(支持事件代理) * @param {*} elem 触发事件的元素 * @param {*} type 事件类型 * @param {*} selector 选择器 * @param {*} fn 事件处理函数 */ function bindEvent(elem, type, selector, fn) { //若只传入了三个参数(即普通的事件绑定),则第三个参数才是事件处理函数 if (fn == null) { // 将第三个参数设置为事件处理函数 fn = selector; // 将选择器置空 selector = null; } // 绑定事件 elem.addEventListener(type, (event) => { // 获取触发事件的元素 const target = event.target; if (selector) { // 传入了选择器,则为事件代理绑定 if (target.matches(selector)) { // 若触发事件的元素与选择器匹配,则执行事件处理函数 fn.call(target, event); // 利用 call 改变事件处理函数中 this 的指向 } } else { // 没有选择器,为普通事件绑定 fn.call(target, event); } }); }
使用
// 普通事件绑定 const btn1 = document.getElementById('btn1') bindEvent(btn1, 'click', function (event) { event.preventDefault() alert(this.innerHTML) }) // 事件代理绑定 const div3 = document.getElementById('div3') bindEvent(div3, 'click', 'a', function (event) { event.preventDefault() alert(this.innerHTML) })
【考题】描述事件冒泡的流程
事件基于 DOM 树形结构顺着触发元素不断向上传播(由内层节点传播到外层节点),触发各级父辈节点对应的事件,若父辈节点中没有阻断事件的冒泡传播,则会一直传播到window 对象。
应用场景:事件代理(参考上文)
【考题】无限下拉图片列表,如何监听每个图片的点击
通过事件代理实现,具体逻辑如下:
- 在列表容器上绑定点击事件
- 点击图片时,会冒泡触发列表容器的点击事件
- 通过 e.target 获取到触发元素
- 通过 matches 判断触发元素是否是图片
- 是图片,则执行相应的代码,不是图片则不执行。