资讯专栏INFORMATION COLUMN

JS DOM Event

WelliJhon / 3093人阅读

摘要:事件处理程序事件侦听器的设定级级首先讲级事件处理程序对事件的方式被称为事件处理程序或事件侦听器,但这两者之间是有区别的。此外,不能对事件目标事件类型执行阶段都相同的对象注册多个相同的事件侦听器。

关于这一篇章有太多对于我来说杂且乱的知识点,单单是分别DOM层级划分我看过的文章就有(0,2,3)的,(0,2)的,由于自己知识掌握还很薄弱所以只能参考别人文章结合自己理解来写,这其中也涉及到一点W3C标准制定史的发展,不了解的像我这样的小白肯定会一头雾水啦。

主要的有,DOM层级事件处理、事件流、熟练一些事件处理方法等 简介

JavaScript中,最重要的就是对事件进行处理。Web应用也是通过事件驱动程序设计其功能的。在事件驱动程序设计中,需要注册不同事件的处理方式。
在注册了事件的处理方式后,浏览器就会在该事件发生时执行所注册的处理方式。所注册的处理方式被称作事件处理程序、事件句柄或事件监听器。
JavaScript程序设计的基本内容之一就是获取需要对事件进行捕捉的元素,并针对该元素注入相应的事件处理程序。

事件处理程序/事件侦听器的设定(DOM 0级/DOM 2级 首先讲DOM 0级事件处理程序

对事件的方式被称为事件处理程序或事件侦听器,但这两者之间是有区别的。

设定方法不同

支持处理元素数量不同

详细点,说一些对事件处理进行设定的方式

指定为HTML元素的属性(DOM 0级)

指定为DOM 元素的属性(DOM 0级)

通过EventTarget.addEventListener进行设定(DOM 2级)

1. 首先是第一个,指定为HTML元素的属性
        

这个例子中,通过字符串对onclick事件处理程序将要执行的JavaScript代码进行了设定。如果包含代码,可以分号分隔,当然,事件另外定义一个函数之后再执行该函数的方式也不会有问题。

优点:

设定步骤简单,确保事件处理程序会在载入时被设定。如果使用第二种方式(DOM元素属性),元素被载入时,其事件处理程序可能还没有注册,这时用户执行任何本应触发事件的操作,也没有效果。

注意:这里的onclick全都是以小写字母书写。HTML不会区分大小写字母,所以改写为onClick也没有问题。但是XHTML会区分大小写字母,所以最好还是使用全部小写的onclick,提高兼容性。

小应用:如果事件处理程序返回一个false值,则会取消该事件的默认行为,(啥是默认行为,比如点击a标签会跳转链接,表单的提交等这些就属于默认行为),例如:当onsubmit事件处理程序返回一个false,表单内容不会被发送,,这可以发现内容有误时返回false取消表单数据发送。或者像下面代码,取消页面跳转。

        BAIDU.com
        

例:

        

我们在DIV上设置CSS样式方便我们查看,此时目标元素就是DIV。随着事件流入.....到目标元素,发现我们的button虽然设置了事件侦听器,却没有执行。因为此时button已经不是目标元素,事件流经过时,它是处于流入阶段也就是捕获阶段的,但button是冒泡阶段调用,所以不会执行button,“忽略了它”。之后便是老套路:DIV-BODY-DOCUMENT.

接下来我们看看捕获阶段:

            var div = document.getElementById("div");
            var btn = document.getElementById("btn");
            // 由内之外
            btn.addEventListener("click",function(e){
                alert("Now to the element BUTTON");
            },true);
            div.addEventListener("click",function(e){
                alert("Now to the element DIV");
            },true);
            document.body.addEventListener("click",function(e){
                alert("Now to the element BODY");
            },true);
            document.documentElement.addEventListener("click",function(e){
                alert("Now to the element DOCUMENT");
            },true);
            // click me!        DOCUMENT-BODY-DIV-BUTTON

点击click,事件流流入,事件目标是button,则到button之前是捕获阶段,恰好这些元素刚好是在捕获阶段设定事件侦听器,则按照DOM数规则,由外至内一层一层执行。但是注意:事件目标button是在目标阶段执行的,不是捕获也不是冒泡,不信?我们用eventPhase来测试:

            btn.addEventListener("click",function(e){
                alert("Now to the element BUTTON");
                alert(e.eventPhase);
            },false);
            // 不论是true还是false,只要点击的是button元素,eventPhase都是返回2

找到规律了吗?也没有什么规律,脑子里能模拟出DOM树就都清楚了。

            btn.addEventListener("click",function(e){
                alert("Now to the element BUTTON");
            },false);
            div.addEventListener("click",function(e){
                alert("Now to the element DIV");
                alert(e.eventPhase);
            },true);
            document.body.addEventListener("click",function(e){
                alert("Now to the element BODY");
            },false);
            document.documentElement.addEventListener("click",function(e){
                alert("Now to the element DOCUMENT");
            },true);
            // click me!        DOCUMENT-DIV(2)-BODY

目标节点是DIV,那事件流流入最深处就是DIV,DIV就是事件目标,则button根本不会执行,不管它是捕获还是冒泡,因为它处于DOM树最深处。

如何取消事件流传播? 1.Event.stopPropagation()

终止事件在传播过程的捕获、目标处理或起泡阶段进一步传播。调用该方法后,该节点上处理该事件的处理程序将被调用,事件不再被分派到其他节点

该方法将停止事件的传播,阻止它被分派到其他 Document 节点。在事件传播的任何阶段都可以调用它。注意,虽然该方法不能阻止同一个 Document 节点上的其他事件句柄被调用,但是它可以阻止把事件分派到其他节点

            btn.addEventListener("click",function(e){
                alert("Now to the element BUTTON");
                e.stopPropagation();
            },false);
            div.addEventListener("click",function(e){
                alert("Now to the element DIV");
            },false);
            document.body.addEventListener("click",function(e){
                alert("Now to the element BODY");
            },false);
            document.documentElement.addEventListener("click",function(e){
                alert("Now to the element DOCUMENT");
            },false);
            // click me!        BUTTON
            

此时只会在button执行一次事件侦听器,之后的传播被阻止了。

但是如果你点击的是DIV,那依然会往上一层一层执行事件侦听器,设置stopPropagation()的是button
以此类推...

2. event.stopImmediatePropagation()

如果你希望阻止当前节点上的其他回调函数被调用的话,你可以使用更激进的event.stopImmediatePropagation()方法。

MDN:如果某个元素有多个相同类型事件的事件监听函数,则当该类型的事件触发时,多个事件监听函数将按照顺序依次执行.如果某个监听函数执行了 event.stopImmediatePropagation()方法,则除了该事件的冒泡行为被阻止之外(event.stopPropagation方法的作用),该元素绑定的后序相同类型事件的监听函数的执行也将被阻止

看MDN这段话我再试着理解理解,一直再说这事件传播,传播,到底是只有跨节点的事件处理程序被触发才能叫传播,同节点上,多个时间侦听器这个不能算是传播,这样理解就好了。

            btn.addEventListener("click",function(e){
                alert("1");
            },false);
            btn.addEventListener("click",function(e){
                alert("2");
                e.stopPropagation();
                // e.stopImmediatePropagation() 
                alert("2-1");
            },false);
            btn.addEventListener("click",function(e){
                alert("3");
            },false);
            div.addEventListener("click",function(e){
                alert("div");
            },false)

对于e.stopPropagation()而言,它能阻止的是所有阶段的事件侦听器传播,结果就是调用该方法的节点上所有的时间侦听器可以触发,但是传播被终止,也就是DIV没有了。弹出1-2-(2-3)-3,这些都是btn节点上的。

换到e.stopImmediatePropagation() ,那它就是精确到节点内的事件侦听器了

            document.documentElement.addEventListener("click",function(e){
                alert("document")
            },true)
            btn.addEventListener("click",function(e){
                alert("1");
            },false);
            btn.addEventListener("click",function(e){
                alert("2");
                e.stopImmediatePropagation(); // 这里往后的节点内事件侦听器不能执行
                //    e.stopPropagation();
                alert("2-1");
            },false);
            btn.addEventListener("click",function(e){
                alert("3");
            },false);
            div.addEventListener("click",function(e){
                alert("div");
            },false)
            // document/1/2/2-1
            // 阻止事件流中当前节点的和所有后续节点的事件监听器的执行。即影响当前结点的事件监听器

这就是MDN:该元素绑定的后序相同类型事件的监听函数的执行也将被阻止,这句话的意思了。

默认操作Event.preventDefault()

在默认情况下,点击a描点元素后,将会跳转至链接页面。而如果在这时执行了Event.preventDefault()方法,则不会发生这一行为。这个方法作用等同于让一个指定为了HTML标签属性或DOM属性的事件处理程序返回一个false

        segmentfault
        

不过也有一些事件无法通过使用preventDefault()方法来中止。blur事件就是其中之一,它是一个焦点移动至其他元素时被触发的事件。
stopPropagation()preventDefault()方法不仅能够用于事件冒泡阶段,在其他阶段中也能够使用这些方法。

IE

IE浏览器下,绑定/删除(attachEvent/detachEvent)、阻止事件冒泡(cancelBubble)、阻止事件的默认行为(returnValue)、用于获取事件的目标(srcElement)等等需要另外探讨,大体相同。到时候我另开一篇来继续学习。

Event接口对象

关于target和currentTarget

这两个属性在不同情况下指向也不尽相同,先来看看概念

target:事件属性可返回事件的目标节点(触发该事件的节点),如生成事件的元素、文档或窗口。

currentTarget 事件属性返回其监听器触发事件的节点,即当前处理该事件的元素、文档或窗口。
在捕获和起泡阶段,该属性是非常有用的,因为在这两个节点,它不同于 target 属性。

event.currentTarget指向事件所绑定的元素,而event.target始终指向事件发生的元素。
        


不管你在哪个节点注册事件侦听器,引发这一系列程序的"罪魁祸首"是button,所以target指向它。如果button节点换成a描点元素,你再点击atarget就指向a(理解为事件目标也行)
currentTarget指向的是这个事件流三个阶段中,事件侦听器绑定的元素

由于我只是初步了解了一下,重点在应用,没有几个实实在在的前端练习是不行的。

目前我只是简单了解而已,灵活运用这些方法需要不断的敲敲敲,练项目造轮子。这里引几个文章吧

DOM事件简介

stopImmediatePropagation应用

事件绑定的几种方式、stopImmediatePropagation和stopPropagation的区别

Javascript DOM Event对象方法详解 - 博客频道 - CSDN.NET

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

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

相关文章

  • 向zepto.js学习如何手动(trigger)触发DOM事件

    摘要:好啦我们已经解决了是啥的疑问了,现在回去开始一步步解读如何实现手动触发事件。我们主要看看这里面几乎含有如何手动触发一个事件的大部分步骤和内容。 前言 前端在最近几年实在火爆异常,vue、react、angular各路框架层出不穷,咱们要是不知道个双向数据绑定,不晓得啥是虚拟DOM,也许就被鄙视了。火热的背后往往也是无尽的浮躁,学习这些先进流行的类库或者框架可以让我们走的更快,但是静下心...

    spacewander 评论0 收藏0
  • 向zepto.js学习如何手动(trigger)触发DOM事件

    摘要:好啦我们已经解决了是啥的疑问了,现在回去开始一步步解读如何实现手动触发事件。我们主要看看这里面几乎含有如何手动触发一个事件的大部分步骤和内容。 前言 前端在最近几年实在火爆异常,vue、react、angular各路框架层出不穷,咱们要是不知道个双向数据绑定,不晓得啥是虚拟DOM,也许就被鄙视了。火热的背后往往也是无尽的浮躁,学习这些先进流行的类库或者框架可以让我们走的更快,但是静下心...

    fuyi501 评论0 收藏0
  • 向zepto.js学习如何手动(trigger)触发DOM事件

    摘要:好啦我们已经解决了是啥的疑问了,现在回去开始一步步解读如何实现手动触发事件。我们主要看看这里面几乎含有如何手动触发一个事件的大部分步骤和内容。 前言 前端在最近几年实在火爆异常,vue、react、angular各路框架层出不穷,咱们要是不知道个双向数据绑定,不晓得啥是虚拟DOM,也许就被鄙视了。火热的背后往往也是无尽的浮躁,学习这些先进流行的类库或者框架可以让我们走的更快,但是静下心...

    Julylovin 评论0 收藏0
  • JS高级程序设计笔记——事件(一)

    摘要:但是通过添加的匿名函数无法移除,最好是在其他地方定义事件处理程序的函数,然后将该函数的名称传给第二个参数。一中的事件对象对象兼容级和级的浏览器将对象传入到事件处理程序中。 一、事件流 假设有如下HTML代码: Event Click me 其DOM树如下图所示:showImg(https://segmentfault.com/img/bVUUWA?w=50...

    guqiu 评论0 收藏0
  • JS 外观模式

    摘要:外观模式在中常常用于解决浏览器兼容性问题。实现外观模式不仅简化类中的接口,而且对接口与调用者也进行了解耦。外观模式的优势是易于使用,而且本身也比较轻量级。 1. 简介 外观模式(Facade)为子系统中的一组接口提供了一个一致的界面,此模块定义了一个高层接口,这个接口值得这一子系统更加容易使用。外观模式在JS中常常用于解决浏览器兼容性问题。 2. 实现 外观模式不仅简化类中的接口,而且...

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

    摘要:使用级方法指定的事件处理程序被认为是元素的方法。用于立即停止事件在中的传播,取消进一步的事件捕获或冒泡。捕获事件目标对象冒泡只有在事件处理程序执行期间,对象才会存在,执行完成后,对象就会被销毁。 引用 事件是我认为前端最特别的地方,这是唯一其他语言不一样的地方,我们通过它与页面进行交互。 事件流 事件流描述的是从页面中接收事件的顺序。IE和网景团队提出流相反的事件流概念。IE事件流是事...

    AlienZHOU 评论0 收藏0

发表评论

0条评论

WelliJhon

|高级讲师

TA的文章

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