浏览器事件

167 阅读2分钟

1.浏览器事件模型过程

浏览器事件模型中的过程主要分为三个阶段:捕获阶段、目标阶段、冒泡阶段。

捕获->目标->冒泡

2.监听事件的第三个参数

window.addEventListener('click', function(e){
    console.log(e.target.nodeName) //指当前点击的元素
    console.log(e.currentTarget.nodeName) //绑定监听事件的元素
}, true) //false为默认为冒泡,true为捕获
  • e.target当前点击的元素
  • e.currentTarget监听事件的元素
  • false或不填为冒泡,true为捕获

3.阻止事件的传播

  • e.stopPropagation()阻止冒泡和捕获阶段的传播。
  • stopImmediatePropagation() 如果有多个相同类型事件的事件监听函数绑定到同一个元素,当该类型的事件触发时,它们会按照被添加的顺序执行。如果其中某个监听函数执行event.stopImmediatePropagation() 方法,则当前元素剩下的监听函数将不会被执行。

4.e.preventDefault()阻止默认事件

5.事件代理/事件委托

事件代理,又称之为事件委托。是JavaScript中常用绑定事件的常用技巧。“事件代理”即是把原本需要绑定在子元素的响应事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。

  • 事件委托,可以减少事件注册,大量节省内存占用。比如在ul上代理所有li的click事件
const ul = document.querySelector("ul");
ul.addEventListener('click', function (e) {
    const target = e.target;
  if (target.tagName.toLowerCase() === "li") {
    // LiList为伪数组
    const liList = this.querySelectorAll("li");
        const realList = Array.form(liList);
        const index = realList.index(target);
    alert(`内容为${target.innerHTML}, 索引为${index}`);
  }
})

6.兼容性

  • attachEvent——兼容:IE7、IE8; 不支持第三个参数来控制在哪个阶段发生,默认是绑定在冒泡阶段
  • addEventListener——兼容:firefox、chrome、IE、safari、opera;

7.封装一个多浏览器兼容的绑定事件函数

class BomEvent {
    constructor(element) {
        this.element = element;
    }

    addEvent(type, handler) {
        if (this.element.addEventListener) {
            //事件类型、需要执行的函数、是否捕捉
            // IE不支持事件捕获
            this.element.addEventListener(type, handler, false);
        } else if (this.element.attachEvent) {
            this.element.attachEvent(`on${type}`, function () {
                // IE7、IE8不支持箭头函数
                handler.call(element);
            });
        } else {
            this.element['on' + type] = handler;
        }
    }

    removeEvent(type, handler) {
        if (this.element.removeEnentListener) {
            this.element.removeEnentListener(type, handler, false);
        } else if (element.datachEvent) {
            this.element.detachEvent('on' + type, handler);
        } else {
            // 赋值为null释放内存
            this.element['on' + type] = null;
        }
    }
}
// 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)
function stopPropagation(ev) {
    if (ev.stopPropagation) {
        ev.stopPropagation(); // 标准w3c
    } else {
        ev.cancelBubble = true; // IE
    }
}
// 取消事件的默认行为
function preventDefault(event) {
    if (event.preventDefault) {
        event.preventDefault(); // 标准w3c
    } else {
        event.returnValue = false; // IE
    }
}