《WebKit 技术内幕》之五(4): HTML解释器和DOM 模型

news2024/11/27 4:15:48

4 影子(Shadow)DOM
        影子 DOM 是一个新东西,主要解决了一个文档中可能需要大量交互的多个 DOM 树建立和维护各自的功能边界的问题。

4.1 什么是影子 DOM
        当开发这样一个用户界面的控件——这个控件可能由一些 HTML 的标签元素组成,这些元素可以组成一颗 DOM 树的子树。这样一个 HTML 控件可以被到处使用,但是问题随之而来,那就是每个使用控件的地方都会知道这个子树的结构。 当网页的开发者需要访问网页 DOM 树的时候,这些控件内部的 DOM 子树都会暴露出来,这些暴露的节点不仅可能给 DOM 树的遍历带来很多麻烦,而且也可能给 CSS 的样式选择带来问题,因为选择器无意中可能会改变这些内部节点的样式,从而导致很奇怪的控件界面。

        如何将内部的节点信息封装起来,就像 C++ 语言的类一样,同时又能够将这些节点渲染出来呢 ? W3C 工作组提出的影子 DOM 概念。影子 DOM 的规范草案能够使得一些 DOM 节点在特定范围内可见,而在网页的 DOM 树中却不可见,但是网页渲染的结果中包含了这些节点,这就使得封装变得容易很多。

        下图描述了 HTML 文档对应的 DOM 树和 “div” 元素包含的一个影子 DOM 子树。当使用 JavaScript 代码访问 HTML 文档的 DOM 树的时候,通常的接口是不能直接访问到影子 DOM 子树中的节点的,JavaScript 代码只能通过特殊的接口方式。

        HTML5 支持了很多新的特性,例如对视频、音频的支持,读者会发现这些元素其实是由很复杂的控制界面组成,这些界面也是使用 HTML 元素编写,但是在 DOM 树中,你无法找到相应的节点,这其实也是使用了影子 DOM 的思想。

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

4.2 WebKit 的支持
        WebKit 已经支持影子 DOM 的规范草案,虽然还存在一些问题。支持影子 DOM 的相关类在目录 “Source/core/dom/shadow” 下,里面的主要类是 ShadowRoot ,表示的是影子 DOM 的根节点。ShadowRoot 类继承自 DocumentFragment 类,所以它同样有 Node 节点的属性和方法,因而在影子 DOM 树的内部,遍历树没有什么特别不同的地方。

        当遍历 HTML 文档对应 DOM 树的时候,WebKit 需要做特别的判断,所以读者会发现在 WebKit 的 Node 类实现中存在大量的条件语句,用来检查当前节点是否是 ShadowRoot 对象,如果是该类的对象,把它作为不同 DOM 树之间的边界。有时候 WebKit 还需要对 ShadowRoot 对象作出特别处理,比如某些情况会略过它的子树,同样的,在事件处理的支持类 EventPathWalker 和 EventRetargeter 中,也需要做一些特别的处理逻辑,原理就是上面所述,细节不再介绍。

4.3 实践:使用影子 DOM
        示例代码 5-2 给出了一个简单的使用 webkitCreateShadowRoot 接口来创建影子 DOM 子树的例子。网页只包含了一个 “div” 元素,JavaScript 代码使用该元素创建了一个影子 DOM 子树的根节点,然后该根节点下加入了两个子女,第一个是图片元素,第二个是 “div” 元素,该元素内部包含了一些文本。

          打开 Chrome 浏览器的开发者工具,然后打开控制台,在其中输入 “document.firstChild.firstChild.nextElementSibling.firstElementChild.firstElementChild” 后会发现结果是空的,根据对应关系 “#document-> html -> head -> body -> div -> null”,虽然网页中没有 ‘head’ 元素,但是 DOM 树仍然会创建该节点。同时读者会发现 “div” 元素没有子女,影子 DOM 子树真的被隐藏起来了,成为真正的影子。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1399711.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在WIN从零开始在QMUE上添加一块自己的开发板(一)

文章目录 一、前言二、源码编译(一)安装Msys2(二)配置GCC工具链(三)安装QEMU构建依赖(四)下载编译QEMU源码 二、QUME编程基础(一)QOM机制(二&…

基于SpringBoot Vue档案管理系统

大家好✌!我是Dwzun。很高兴你能来阅读我,我会陆续更新Java后端、前端、数据库、项目案例等相关知识点总结,还为大家分享优质的实战项目,本人在Java项目开发领域有多年的经验,陆续会更新更多优质的Java实战项目&#x…

ClickHouse与Doris数据库比较

概述 都说“实践是检验真理的唯一标准”,光说不练假把式,那么本文就通过实际的测试来感受一下Doris和clickhouse在读写方面的性能差距,看看Doris盛名之下,是否真有屠龙之技;clickhouse长锋出鞘,是否敢缚苍…

Vagrant创建Oracle RAC环境示例

利用Vagrant安装Oracle RAC(默认为non-CDB模式),生成2台虚机,耗时约1小时。 node1: -----------------------------------------------------------------node1: INFO: 2024-01-11 18:25:54: Make create database commandnode1: …

多人在线聊天交友工具,匿名聊天室网站源码,附带搭建教程

源码介绍 匿名聊天室(nodejs vue) 多人在线聊天交友工具,无需注册即可畅所欲言!你也可以放心讲述自己的故事,说出自己的秘密,因为谁也不知道对方是谁。 运行说明 安装依赖项:npm install 启动…

react学习笔记(复习)

React简介 react是什么? React用于构建用户界面的JS库。是一个将数据渲染为HTML视图的开源JS库。 为什么学? 1.原生JS操作DOM繁琐,效率低 2.使用JS直接操作DOM,浏览器会进行大量的重绘重排 3.原生JS没有组件化编码方案,代码…

Linux-ionde(软硬件链接)剖析

概述 文件是存储在硬盘上的,硬盘的最小存储单位叫做扇区sector,每个扇区存储512字节。操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个块block。这…

OpenAI的DALL·e2生成的AI图像有时会带有偏见或NSFW

专家警告说,OpenAI的图像生成模型DALLe2可能玩起来很有趣,但它生成的图片可能会带有刻板印象和偏见,甚至是生成NSFW图片,因此在现实世界中部署会有风险。 OpenAI公司承认“如果没有足够的防护措施,像DALLe2这样的模型…

k8s节点RouteCreated为false

出现该情况后,一般是初始化节点失败。因此,需要把节点从集群中移除,再加入到集群中,即可解决。 通常出现这个状况后,该节点上是没有被分配pod ip的,可以通过命令查看: # 发现没有PodCIDR、PodC…

DHCP原理

目录 DHCP应用场景DHCP基本原理DHCP报文类型地址池DHCP工作原理DHCP租期更新DHCP重绑定IP地址释放 DHCP应用场景 在大型企业网络中,会有大量的主机或设备需要获取IP地址等网络参数。如果采用手工配置,工作量大且不好管理,如果有用户擅自修改网…

vue3前端开发,子组件向父组件传递数据练习

vue3前端开发,子组件向父组件传递数据练习&#xff01; <script setup> import Child from ./Child.vue const getMsg (msg)>{console.log(msg); } </script> <template><h3>Parent</h3><!--绑定事件--><Child get-Msg"getM…

回调地狱与解决方案

什么是回调地狱&#xff1f; 简单理解就是回调函数嵌套回调 示例&#xff1a; setTimeout(() > {console.log(1);setTimeout(() > {console.log(2);setTimeout(() > {console.log(3);}, 1000);}, 2000)}, 3000)如上代码所示&#xff0c;回调函数嵌套回调&#xff0c;就…

QoS简介

QoS产生的背景 网络的普及和业务的多样化使得互联网流量激增&#xff0c;从而产生网络拥塞&#xff0c;增加转发时延&#xff0c;严重时还会产生丢包&#xff0c;导致业务质量下降甚至不可用。所以&#xff0c;要在网络上开展这些实时性业务&#xff0c;就必须解决网络拥塞问题…

电商系统设计到开发02 单机性能压测

一、前言 接着上篇文章&#xff1a;电商系统设计到开发&#xff08;第一版&#xff09;-CSDN博客 已经开发的代码&#xff0c;今天我们对上面开发的代码进行压力测试&#xff0c;看看单机部署的情况下&#xff0c;性能表现如何。代码地址&#xff1a;风萧萧兮/concurrency-en…

Linux中关于head命令详解

head的作用 head用于查看文件的开头部分的内容。 head的参数 -q隐藏文件名-v 显示文件名-c<数目>显示的字节数-n<数目>显示的行数 head的案例 # 查看yum.log前五行内容 head -5 yum.log

对于随机生成图片接口浏览器走缓存的问题

前提场景 目前有一个api 他可以随机生成一张图片&#xff0c;我通过v-for循环一个Array渲染出来几个img 并且都调用了该接口&#xff0c;但是每个img都是一样的图片 具体代码如下 <div class"icon-group-box" v-for"item in groupList" :key"item…

Oracle篇—参数文件在11gRAC或12cRAC的启动位置介绍

☘️博主介绍☘️&#xff1a; ✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、Linux&#xff0c;也在积极的扩展IT方向的其他知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&#xff0c;并且也会默默的点赞收藏加关注❣…

让Mac与Windows合二为一:Microsoft Remote Desktop for Mac的魅力

在数字时代&#xff0c;远程连接已成为工作、学习和生活的必备工具。而Microsoft Remote Desktop for Mac正是这样一款能够让你随时随地&#xff0c;轻松连接到Windows系统的强大工具。 Microsoft Remote Desktop for Mac不仅提供了高效、稳定的远程访问体验&#xff0c;更凭借…

黑马程序员-瑞吉外卖-day4

实现账号的启动禁止 EmployeeController PutMappingpublic R<String> update(RequestBody Employee employee){employeeService.updateById(employee);return R.success("员工信息修改成功");} 出错 解决 common目录下 引入JacksonObjectMapper package com…

Sentinel 降级、限流、熔断

前言 在现代分布式系统中&#xff0c;如何有效地保护系统免受突发流量和故障的影响&#xff0c;是每个开发人员和架构师都需要思考的重要问题。在这样的背景下&#xff0c;Sentinel作为一个强大的系统保护和控制组件&#xff0c;为我们提供了降级、限流、熔断等多种策略&#…