前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Webkit底层原理(4)--DOM事件机制和Shadow DOM

Webkit底层原理(4)--DOM事件机制和Shadow DOM

作者头像
从入门到进错门
发布2019-10-22 14:46:06
1.2K0
发布2019-10-22 14:46:06
举报
文章被收录于专栏:前端菜鸟变老鸟

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/caomage/article/details/102162100

一、DOM事件机制

1. 事件的工作过程

事件在工作过程中使用两个主体,第一个是事件(event),第二个是事件目标(EventTarget)。每个事件都有属性来标记该事件的事件目标。当事件到达事件目标的时候,在这个目标上注册的监听者(EventListeners)都会被触发调用,当然这些监听者的调用顺序是不固定的,所以不能依赖监听者注册的顺序来决定你的代码逻辑。 事件处理最重要的部分就是事件捕获(Event capture)和事件冒泡(Event bubbling)这两种机制。如下图:

当渲染引擎接收到一个事件的时候,它会通过HitTest(Webkit中的一种检查触发事件在哪个区域的算法)检查哪个元素是直接的事件目标。在上图中,以“img”元素为例,假设它是事件的直接目标,这样,事件会经过自顶向下和自底向上两个过程。

事件的捕获是自顶向下,这就是说,事件是先到document节点,然后一路到达目标节点。在上图中的顺序就是“#document-->html-->body-->img”。事件可以在这一传递过程中被捕获,只需要在注册监听函数的时候设置相应的参数即可。addEventListener的第三个参数就是表示这个含义。默认情况下,其他节点不捕获这样的事件。如果网页注册了这样的监听函数,那么监听函数的回调函数会被调用,函数可以通过事件的stopPropagation函数来阻止事件向下传递。

事件的冒泡过程是自底向上,它的默认行为是不冒泡,但是事件包含一个时候冒泡的属性。当这一属性为真的时候,渲染引擎会将该事件首先传递给事件目标节点的父亲,然后是父亲的父亲,一次类推。同捕获动作一样,这些监听函数可以使用preventDefault函数来阻止。

2. Webkit的事件处理机制

DOM的事件分为很多种,与用户相关的只是其中一种,称为UIEvent,其他的包括CustomEvent、MutationEvent等。UIEvent又可以分为很多种:FocusEvent、MouseEvent、KeyboardEvent、CompositionEvent等。

基于Webkit的浏览器事件处理过程,首先是做HitTest,查找事件发生处的元素,检测该元素有无监听者。如果网页的相关节点注册了事件的监听者,那么浏览器会把事件派发给Webkit内核来处理。同时,浏览器也有可能需要理解和处理这样的事件。这主要是因为有些事件浏览器必须响应,从而对网页作默认处理。比如用户使用鼠标翻滚网页。假如当前鼠标的位置就在一个元素之上,并且该元素注册了监听函数,就会导致竞争冲突,所以我们应该在监听代码中调用preventDefault函数来阻止浏览器触发它的默认行为,也就是不需要滚动整个网页。

当事件的派发机制遇到网页的盒模型特别是很多个盒的时候,情况变得比较复杂,这是因为事件需要在多个盒子和多个DOM树之间传递。当触控事件(Touch Events)被引入之后,情况更复杂了。

最后再来看看之前提到的事件从浏览器到达Webkit内核之后,Webkit内部调用的过程,这一过程比较简单,主要是EventHandler类。EventHandler类是处理事件的核心类,它除了需要将各种事件传递给JavaScript引擎以调用相应的监听者之外,还会识别鼠标事件来触发调用右键菜单、拖放效果等工作。

二、影子(Shadow)DOM

影子DOM主要解决了一个HTML文档中可能需要大量交互的多个DOM建立和维护各自功能边界的问题。影子DOM 为Web组件中的DOM和CSS提供了封装,使得这些东西与主文档的DOM保持分离,也可以在一个Web组件外部使用影子DOM本身。

1. 什么是Shadow DOM

想象一下网页的基础库开发者想要开发这样一个用户界面的控件:

  1. 这个控件可能由一些HTML元素组成,
  2. 这些元素可以组成一颗DOM树的子树,
  3. 这个控件可以被到处使用。

问题随之而来,每个使用控件的地方都会知道这个子树的结构。当网页的开发者需要访问网页DOM的时候,这些控件内部的DOM子树就会暴露出来,这些控件内部的节点不仅可能会给DOM的遍历带来麻烦,而且也可能因为无意中被CSS选中而改变样式。

于是W3C提出了Shadow DOM,它可以使得一些DOM节点在特定的范围内可见,而在网页的DOM树中却不可见。这使得封装组件变得容易很多。当使用JavaScript代码访问HTML文档的DOM树的时候,普通的接口是不能直接访问到Shadow DOM中的节点的,JavaScript需要特殊的接口才能访问。具体可以看一下Shadow DOM文档

HTML5中有很多新特性,例如视频音频,我们会发现这些元素都会比较复杂,但是在DOM树中就只会看见audio和video标签,这其实就是使用了Shadow DOM的思想。

既然Shadow DOM在整个网页DOM树中不可见,那么事件如何处理呢?事件中需要包含事件目标,这个目标当然不能是不可见的节点,所以事件目标其实就是包含Shadow DOM子树的节点对象。事件捕获的逻辑没有变化,在Shadow DOM子树内也会继续传递。当Shadow DOM子树中事件向上冒泡的时候,Webkit会同时向整个文档的DOM上传递该事件,以避免一些奇怪的行为。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/10/05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、DOM事件机制
    • 1. 事件的工作过程
      • 2. Webkit的事件处理机制
      • 二、影子(Shadow)DOM
        • 1. 什么是Shadow DOM
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档