细说Javascript事件的那些事儿

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_41196185/article/details/82687730

事件是我们开发过程中经常会用到的,像click,load,mouseenter,mouseleave等等。而我们在使用这些事件的时候,经常会忽略了它们的历史渊源。

事件的DOM级别

DOM(Document Object Model,即文档对象模型)级别经历了从DOM0到DOM3的变迁。而关于事件的级别却只有DOM0级,DOM2级,DOM3级三种,独独缺了DOM1级事件,因为在DOM1阶段,W3C并未对事件这方面做什么改动。

DOM0级事件

绑定

DOM0级事件约束了事件的绑定方式,有两种方式。

  • 在html标签上用on+事件名的形式绑定,如:
<div id="btn" onclick="clickHandler"></div>
  • 通过dom对象进行绑定
document.getElementById('btn').onclick = function(e) {
    console.log(e)
}

清理事件

只要给该事件赋值null即可

document.getElementById('btn').onclick = null

优势

没有兼容问题,各大浏览器均支持。

缺点

每个元素的每种事件只能绑定一个事件处理器

DOM2级事件

DOM2级提供了更灵活的事件监听方式。

监听事件addEventListener

可以为元素添加多个事件处理函数,而事件触发时会按照添加时的顺序依次调用。写法如下:

document.getElementById('btn').addEventListener('click', function(e) {
    console.log(e)
}, true)

addEventListener 接收三个参数,第三个参数决定了事件处理函数的执行时机,true表示在事件捕获阶段执行,而false表示在事件冒泡阶段执行。默认为false

注意:IE对addEventListener的支持性不是很好,从Can I Use上可以看到,IE11才完全支持addEventListener

IE支持性不好

IE支持的是attachEvent,因此为了兼容IE低版本,我们需要自己封装一下代码

function addEvent(element, type, callback, isCapture) {
    if (event.addEventListener) {
        // 如果支持DOM2级addEventListener
        element.addEventListener(type, callback, isCapture)
    } else if (element.attachEvent) {
        // 如果支持IE attachEvent
        element.attachEvent('on' + type, callback)
    } else {
        // 啥都不支持,别说了,用最老套的吧
        element['on' + type] = callback
    }
}

事件捕获与事件冒泡

这里又必须啰嗦一下事件捕获与事件冒泡的区别了。

  • 事件捕获是指事件从最不确定的对象(body)开始触发,然后到最精确的事件绑定的对象上。

  • 事件冒泡则与之相反,从事件绑定的对象开始触发,一直传播到body

通俗地讲,事件捕获从爷爷辈开始触发,继而通知到父亲,最后通知到本人;而事件冒泡从本人开始触发,然后会把事件通知到父亲,爷爷,祖爷爷等等。

阻止事件冒泡

事件冒泡往往是我们不想要的结果。你把事件告诉我就行了,还TM告诉其他人干嘛,这不是浪费人力资源吗?那么如何阻止事件冒泡呢?

W3C标准中指定的阻止冒泡的方法为e.stopPropagation(),但是IE你懂的,低版本IE不支持。兼容写法如下:

function stopPropagation(event) {
    if (event.stopPropagation) {
        event.stopPropagation()
    } else {
        event.cancelBubble = true
    }
}

移除监听removeEventListener

与addEventListener类似,用法如下:

document.getElementById('btn').removeEventListener('click', function(e) {
    console.log(e)
}, true)

兼容IE

function removeEvent(element, type, callback, isCapture) {
    if (event.removeEventListener) {
        // 如果支持DOM2级removeEventListener
        element.removeEventListener(type, callback, isCapture)
    } else if (element.detachEvent) {
        // 如果支持IE detachEvent
        element.detachEvent('on' + type, callback)
    } else {
        // 啥都不支持,别说了,用最老套的吧
        element['on' + type] = null
    }
}

阻止事件默认行为

浏览器有一些事件的默认行为,如点击a标签会打开新链接,点击右键会弹出菜单。有些场景下,我们需要阻止事件的默认行为。标准的方法是preventDefault(),但是为了兼容IE,我们经常需要这样写:

function stopDefault(event) {
    if (event.preventDefault) {
        event.preventDefault()
    } else {
        // 或者return false,该语法实质在操作window.event.returnValue的值
        window.event.returnValue = false;
    }
}

要知道,return false其实是阻止了事件的继续执行,所以说,在阻止默认事件行为的同时,它也阻止了冒泡,这一点上与preventDefault 方法还是有区别的。但是在网上看到一哥们提到,return false 不是每次都有用,特别是在mouseover等一些特殊事件上。所以不要过分地依赖return false

DOM3级事件

DOM3级事件在DOM2级事件的基础上新增了更多的事件类型,主要有:

  • UI事件,如:load、scroll

  • 焦点事件,元素获得或失去焦点时触发,如:blur、focus

  • 鼠标事件,用户通过鼠标在页面执行操作时触发如:dbclick、mouseup

  • 滚轮事件,使用鼠标滚轮或类似设备时触发,如:mousewheel

  • 键盘事件,如:keydown、keyup、keypress

  • 变动事件,DOM结构发生变化时触发,如:DOMsubtreeModified

DOM3还支持用户自定义事件,主要API有三个

// 创建自定义事件
document.createEvent(customedEventName)
// 事件初始化
event.initEvent()
// 事件触发
element.dispatchEvent()

本人也没用过自定义事件,目前不知道实际应用场景。

猜你喜欢

转载自blog.csdn.net/weixin_41196185/article/details/82687730