专栏首页达摩兵的技术空间js高程之事件通识篇(一)

js高程之事件通识篇(一)

事件流

源头

在早期的浏览器厂商都认为页面中的元素事件都不仅仅是当前元素上,而是相关的其他元素甚至整个页面都应该相关的机制。但有意思的是,早期的两个开发团队分别是ie和Netscape却提出了完全相反的事件流概念。也就是下面要介绍的两种。

场景:在很多时候我们会遇到类似的问题,我最早遇到的场景是在a标签上定义了连接地址,然后a标签内定义的子标签定义的其他点击事件会在执行前就先页面跳转了。 常识:作为常识我们要知道事件函数中的this指向的是被点击的目标元素,稍后的讲解中会区分目标元素以及托管的元素。

冒泡

ie提出的是冒泡,也就是从最具体的触发元素对象一直向上传递。

graph LR
childElement(span)-->parentNode(div)
parentNode(div)--> parentNode2(body)
let button = document.getElementById("button")
button.addEventListener('click',function(e){
    //come code 
    //避免冒泡
    e.preventDefault()
})

捕获

捕获与冒泡的机制相反,是指元素会捕获所有子元素的事件,进而检查自己是否具有事件绑定,从而触发。

这个就不画流程图了,写下事件的定义好了,如果利用捕获机制,定义事件会写成下面这样。

let ul = container.getElementById("container")
container.addEventListener("click",funtion(e){
// 不考虑兼容写法
    let target = e.target
//监听到点击后,查看具体目标是什么,具体处理    

    switch(target){
        case 'span' : some code
    }
})

dom事件流

dom2级的事件流规定:事件流包括三个阶段:事件捕获阶段、目标阶段、冒泡阶段。

在多数的浏览器里规定了事件不会在捕获阶段触发事件,只会在目标阶段触发,而后才会触发冒泡阶段。但有的浏览器在捕获阶段也会触发事件,于是导致了两次父元素的事件触发。

待进一步验证谷歌的事件机制是怎样的 。。。

事件处理对象

html事件处理函数

这一类在我们原生开发的时候很常见,直接用标签的事件属性绑定函数,在vue的框架写法中也是类似的写法,至于其底层是html事件处理还是下面的dom0级,后面我会在查看对应的源码,给大家分析下vue的@click 底层是是如何处理事件的。

dom0级处理函数

将一个函数赋值给一个事件处理属性,这种方式跨浏览器,写法简单,兼容性好,但是它需要一个对元素的引用,所以如果这个事件如果定义在元素的前面,那么事件就不会绑定上。

其中,处理函数中的this指的是当前元素对象。

let btn = document.getElementById('btn');
btn.onclick = function(){
    console.log(this)
}

dom2级事件

dom2级事件定义了两个方法,用于处理指定程序和删除事件处理程序的操作。所有的dom节点都包含这样的方法,这个方法支持三个参数,要处理的事件名,处理事件的函数,和一个布尔值。如果为true,代表捕获阶段处理,如果为false,代表冒泡阶段调用函数。

let btn = document.getElementById('btn');
btn.addEventListener("click",  function(){
    console.log(this)
},false)
btn.addEventListener("click",  function(){
    console.log('hello world')
},false)

dom2级与前面方式的区别在于可以为一个事件绑定多个函数而不会是替换关系,这个更符合我们的实际需求。

通过addEventListener添加的函数只能通过removeEnentListener来移除,这意味着如果你添加的是匿名函数,是无法移除的,因为匿名函数没有对应的名称和指引找到,在移除具名函数的时候,只要第二个参数写具名函数的名称即可。

ie事件处理程序

attachEvent与detatchEvent 分别可以用来为ie增加和移除事件监听程序。与dom0级不同的是,其是为全局添加的,也就是事件里的this为window。

与dom2级的监听程序一样,也可以为同一个事件增加多个监听,但其没有配置项,默认的是在捕获阶段捕获事件的。

需要注意的时候事件的执行顺序不是按照添加的顺序,而是按照相反的顺序执行的。

跨浏览器的监听写法

这里我们稍微带一下设计模式里的外观模式,外观模式就是让用户不关心具体实现和方案分配,只关心效果的设计模式。

也可以理解为通过一个暴露接口可以调用底层的api的一个设计。

那么我们浏览器的兼容写法其实也是外观模式的设计思路。

基于以上的常识,我们用外观模式设计的监听程序应该是这样写的:

var EventUtil = {
    addHandler:function(ele,type,handler){
        if(ele.addEventListener){
            ele.addEventListener(type,handler,false)
        } else if(ele.attactEvent){
            ele.attactEvent(type,handler)
        } else{
            ele['on'+type] = handler
        }
    },
    removeHandler:function(ele,type,handler){
        //codes here
    }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • js事件委托

    事件委托也叫事件代理,事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

    RobinsonZhang
  • 浏览器中flash设置最强教程

    承接上文,我讲到了前端如何判断浏览器是否安装或者禁用了flash插件,本文就重点讲述各个常见浏览器的详细设置教程,有图有文字描述,需要的产品经理请接好哦。

    RobinsonZhang
  • break与continue跳出的理解

    如果你还缺乏对break与continue断点跳出循环的正确理解,请复制粘贴以下代码,思考得出答案(代码涉及标签语句的用法,如果不会的请自行百度)。

    RobinsonZhang
  • C#系列学习笔记之事件

    需要使用winform来实现传入图片的base64值,调用接口,返回结果这样的一个功能。大致的设置如下图:

    算法发
  • javascript事件流的原理

    事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字。

    前端老鸟
  • 微服务架构下的数据一致性保证(二)

    大家好,今天是第二次在这里给大家分享数据一致性的话题,在第一篇分享中我们介绍了微服务架构下应该满足数据最终一致性原则,并介绍实现最终一致性3种模式。 本文是...

    yuanyi928
  • 事件机制

    DOM事件模型分为捕获和冒泡。一个事件发生后,会在子元素和父元素之间传播(propagation)。事件传播分为三个阶段:

    Cloud-Cloudys
  • JavaScript中的Event(事件)详解

    时间静止不是简史
  • 事件溯源模式

    使用只追加存储来记录对数据采取的完整系列操作,而不是仅存储域中数据的当前状态。 该存储可作为记录系统,可用于具体化域对象。 这样一来,无需同步数据模型和业务域,...

    只喝牛奶的杀手
  • 在微服务中使用领域事件|洞见

    稍微回想一下计算机硬件的工作原理我们便不难发现,整个计算机的工作过程其实就是一个对事件的处理过程。当你点击鼠标、敲击键盘或者插上U盘时,计算机便以中断的形式处理...

    ThoughtWorks

扫码关注云+社区

领取腾讯云代金券