资讯专栏INFORMATION COLUMN

js事件详解

AlienZHOU / 2000人阅读

摘要:使用级方法指定的事件处理程序被认为是元素的方法。用于立即停止事件在中的传播,取消进一步的事件捕获或冒泡。捕获事件目标对象冒泡只有在事件处理程序执行期间,对象才会存在,执行完成后,对象就会被销毁。

引用

事件是我认为前端最特别的地方,这是唯一其他语言不一样的地方,我们通过它与页面进行交互。

事件流

事件流描述的是从页面中接收事件的顺序。IE和网景团队提出流相反的事件流概念。IE事件流是事件冒泡流,而网景是事件捕获流。

事件冒泡

IE的事件流叫做事件冒泡,即事件开始由最具体的元素接收,然后逐级向上传播到较为不具体的节点。




    
    Document


    
点我点我

如果你单击了div元素,那么click事件会按照如下事件传播




document
点击元素会从最具体的元素向上传播。所有现代浏览器都支持事件冒泡,但是具体实现还是有些差别,IE5.5及更早版本的事件会跳过元素。

事件捕获

网景公司提出的另一个事件流叫做事件捕获,事件捕获的思想上不太具体的节点应该更早接收到事件,而最具体的元素应该最后接收到事件,事件捕获的目的的事件到达预期目标之前捕获它。之前的例子来说就是

document
html
body
div

由于老版的浏览器不支持事件捕获,所以我们一般使用的都是事件冒泡。

DOM事件流

DOM2级规定的事件流包含三个阶段,事件捕获阶段、处于目标阶段和事件冒泡阶段。

事件处理程序

事件就是用户或浏览器自身执行的某种动作,click、load、mouseover,都是事件的名字。而响应某个事件的函数就叫做事件处理程序,click的事件处理程序就是onclick,load事件处理程序就是onload。

HTML事件处理程序

在HTML中指定事件处理程序有两个缺点,一是存在时间差,如果页面已经出现了HTML元素,但是js还没加载完,这时候就会报错。还有就是会造成js代码与HTML代码耦合。

DOM0级事件处理程序

通过js指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性。这种为事件处理程序赋值的方法是在第四代web浏览器中出现的,现在浏览器还支持这种操作。
使用DOM0级方法指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序是在元素的作用域中运行;程序中的this指向当前元素。

var btn = document.getElementById("mybtn");
btn.onclick = function () {
    alert(this.id);    //mybtn
}

DOM0级添加的事件处理程序会在事件流的冒泡阶段被处理。
也可以通过删除DOM0级方法指定的事件处理程序,只要像下面这样将事件事件处理程序属性设置为null就可以了。
将事件处理程序设置为null之后,再单击按钮将不会有任何动作发生。

DOM2级事件处理程序

“DOM2级事件”定义了两个方法,用于处理指定和删除事件处理程序的操作:addEventListener()和 removeEventListener()。所有DOM节点都包含这两个方法,并且它们都接收三个参数,要处理的事件名、事件处理函数、一个布尔值。最后一个参数如果是true,表示在捕获阶段处理程序,如果是false,表示在捕获阶段处理程序。
与DOM0级方法一样,这里的this指向是添加处理事件的元素中执行,使用DOM2级可以为元素添加多个事件处理程序,顺序按添加事件的顺序执行。通过addEventListener添加的事件处理程序只能通过removeEventListener移除,移除传入的参数必须与添加时的参数相同,这就以为添加的匿名函数无法移除。

IE中事件处理程序

IE实现了两个方法:attachEvent和detachEvent。这两个方法,通过attachEvent添加的事件处理程序都会被添加到冒泡阶段,注意attachEvent第一个参数是onclick,而非addEventListener方法中的click。在IE中使用attachEvent的this指向的是全局作用域。

var btn = document.getElementById("myBtn");
btn.attachEvent("onclick", function () {
    console.log(this === window); // true
})

同样的可以添加多个事件,不过事件的执行顺序是相反的。
我们可以封装跨浏览器处理程序。

var EventUtil = {

        addHandler: function (ele, type, handler) {
            if (ele.addEventListener) {
                ele.addEventListener(type, handler, false)
            } else if (ele.attachEvent) {
                ele.attachEvent(`on${type}`, handler)
            } else {
                ele[`on${type}`] = handler
            }
        },
        removeHandler: function (ele, type, handler) {
            if (ele.removeEventListener) {
                ele.removeEventListener(type, handler, false)
            } else if (ele.detachEvent) {
                ele.detachEvent(`on${type}`, handler)
            } else {
                ele[`on${type}`] = null
            }
        },
    }
DOM中的事件对象

无论指定事件处理程序时用的什么方法,都会传入一个event对象。事件处理程序内部,对象this的值等于currentTarget的值,而target只包含事件的实际目标,如果直接将事件处理程序指定给了目标元素,this、currentTarget和target包含相同的值。

var bth = document.getElementById("myBth");

bth.onclick = function (e) {
    console.log(e.currentTarget === this); // true
    console.log(e.target === this); // true
}

可以通过e.preventDefault()阻止事件的默认行为,cancelable为true的事件才可以阻止。
stopPropagation()用于立即停止事件在DOM中的传播,取消进一步的事件捕获或冒泡。

var btn = document.getElementById("myBtn");

btn.onclick = function (e) {
    e.stopPropagation();
}

document.body.onclick = function (e) {
    //不执行
}

可以用eventPhase来确定事件处于哪个事件流阶段。
1:捕获
2:事件目标对象
3:冒泡
只有在事件处理程序执行期间,event对象才会存在,执行完成后,对象就会被销毁。

IE中的事件对象

在使用DOM0级方法添加事件处理程序时,event 对象做为window对象的一个属性存在。

var btn = document.getElementById("myBtn");
btn.onclick = function () {
    var event = window.event;
    console.log(event.type)
}

var btn = document.getElementById("myBtn");
btn.onclick = function () {
    var event = window.event;
    console.log(event.srcElement === this)  //true
    //event.srcElement 相当于DOM中的target
}

var btn = document.getElementById("myBtn");
btn.attachEvent = function (event) {
    console.log(event.srcElement === this)  //false
    //this是window
}

returnValue属性相当于preventDefault,cancelBubble属性stopPropagation()方法类型,不过其只能阻止冒泡,因为低版本IE只支持冒泡。

跨浏览器的事件对象
var EventUtil = {
    addHandler: function (ele, type, handler) {

    },
    getEvent: function (event) {
        return event ? event : window.event
    },
    getTarget: function (event) {
        return event || event.srcElement
    },
    preventDefault: function (event) {
        if (event.preventDefault) {
            event.preventDefault()
        } else {
            event.returnValue = false
        }
    },
    stopPropagation: function (event) {
        if (event.stopPropagation) {
            event.stopPropagation()
        } else {
            event.cancelBubble = true
        }
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83540.html

相关文章

  • 【连载】前端个人文章整理-从基础到入门

    摘要:个人前端文章整理从最开始萌生写文章的想法,到着手开始写,再到现在已经一年的时间了,由于工作比较忙,更新缓慢,后面还是会继更新,现将已经写好的文章整理一个目录,方便更多的小伙伴去学习。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 个人前端文章整理 从最开始萌生写文章的想法,到着手...

    madthumb 评论0 收藏0
  • JS基础篇--JS之onunload、onbeforeunload事件详解

    摘要:事件事件在用户退出页面时发生。注意事件同样触发了页面载入事件事件。如图所示大体一句话描述和支持事件但是或者不支持该事件。浏览器兼容情况完美支持不支持文字提醒信息不支持如图所示使用遇到的凡是标签都会触发事件包括这种。 简介 onunload,onbeforeunload都是在刷新或关闭时调用,可以在脚本中通过 window.onunload来调用。区别在于onbeforeunload在o...

    rollback 评论0 收藏0
  • js事件委托详解

    摘要:先说事件流的事件流分为个阶段捕获目标冒泡。如果是每个都去单独绑定事件明显不科学,毕竟去拿列表也是毕竟消耗性能的,同时每个事件绑定的回调函数也会占用大量的内存。那如果有动态插入的元素呢于是委托就可以用上了。 先说事件流 js的事件流分为3个阶段:捕获、目标、冒泡。即事件来了,先从上到下传播(捕获),到达目标节点(目标),然后在往上传播(冒泡)。看下图: showImg(https://s...

    Sleepy 评论0 收藏0
  • js事件委托详解

    摘要:先说事件流的事件流分为个阶段捕获目标冒泡。如果是每个都去单独绑定事件明显不科学,毕竟去拿列表也是毕竟消耗性能的,同时每个事件绑定的回调函数也会占用大量的内存。那如果有动态插入的元素呢于是委托就可以用上了。 先说事件流 js的事件流分为3个阶段:捕获、目标、冒泡。即事件来了,先从上到下传播(捕获),到达目标节点(目标),然后在往上传播(冒泡)。看下图: showImg(https://s...

    GeekQiaQia 评论0 收藏0
  • js事件详解

    摘要:所有节点中都包含这两个方法,并且它们都接受个参数要处理的事件名作为事件处理程序的函数和一个布尔值。最后这个布尔值如果是,表示在捕获阶段调用事件处理程序如果是,表示在冒泡阶段调用事件处理程序。 事件处理的方法: 1、直接在html中编写 例如: 但是这样处理的事件存在两个缺点,一个是时间差问题,一个是不同浏览器对标识符的解析有差异,很可能会在访问非限定对...

    TerryCai 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<