likes
comments
collection
share

Web components - shadow dom 详解

作者站长头像
站长
· 阅读数 60

Web平台只提供了一种原生的方法去隔离代码块,iframe,但对大部分需要封装的场景来说,iframe太重而且限制太多。今天介绍的就是另一个技术, 也就是shadow dom(但是浏览器的支持性并不是很好)。

一、在控制台审查元素里显示shdow dom 的步骤

  • 测试页面
  • 测试浏览器: 谷歌(至于其他浏览器,没有测试)
  1. 打开控制台,点击右上角设置齿轮icon

Web components - shadow dom 详解

  1. 在设置页面勾选元素里的显示用户代理shdow dom 选项

Web components - shadow dom 详解

  1. 勾选前元素审查只能看到video + source,也无法选中图上的播放键是怎么实现的, 因为对用户来说,这是个黑盒

Web components - shadow dom 详解

Web components - shadow dom 详解

  1. 打开shadow dom 配置项后, 可以在控制台看到 #shdow-root(user-agent), 展开后,里面就是video 播放键, 音量键, 进度条的具体实现,也可以选中。虽然我们就只有一行的代码,但是也实现了播放暂停音量等控件功能,这都是shadow dom 的功劳。
<video width="320" height="240" controls autoplay>
  <source src="movie.ogg" type="video/ogg">
</video>

Web components - shadow dom 详解

Web components - shadow dom 详解

备注:  Firefox(从版本 63 开始),Chrome,Opera 和 Safari 默认支持 Shadow DOM。基于 Chromium 的新 Edge 也支持 Shadow DOM;而旧 Edge 未能撑到支持此特性。

二、什么是shadow dom

shadow-dom 其实是浏览器的提供一种“封装”能力,提供了一种强大的技术去隐藏一些实现细节。但是它们是实际存在的,在 chrome 中,我们可以通常审查元素去查看它们的具体 DOM 实现。

它允许在浏览器渲染文档(document)的时候向其中的 Dom 结构中插入一棵 DOM 元素子树,但这棵子树(shadow-dom)并不在主 DOM 树中。

术语:

  • Shadow host: 宿主对象
  • Shadow root:根节点
  • Shadow tree: Shadow DOM内部的DOM树。
  • Shadow boundary:Shadow DOM 结束的地方,也是常规 DOM 开始的地方。

如何通过css 控制shadow dom 内部的内容

常规的CSS选择器并不能获取到shadow DOM子树,

  • 伪元素:元素上有pesudo 属性的话, 就可以通过伪元素控制

Shadow 的 API:

attachShadow()方法:创建shadow root

  • mode模式:
    • open: 允许通过js方法来获取 Shadow DOM
    • close:拒绝从 js 外部访问关闭的 shadow root 节点

旧api(貌似已弃用):createShadowRoot()创建shadow root。但是子节点内容不可见

属性:

  • element.shadowRoot: 访问根节点

创建shadow dom 结构

使用相关 DOM 操作来创建元素的 Shadow DOM 结构,添加属性等: 如appendChild

eg:

let customElement = document.querySelector("#customDiv");
let shadow = customElement.attachShadow({mode: 'open' || 'close'});
console.log(customElement.shadowRoot); // 返回一个 ShadowRoot 对象 || null
shadow.appendChild(document.createElement("p")).innerHTML="中国";

注意事项:

⚠️ 如果一个元素底下已经有一个 Shadow DOM 挂载,继续给它挂载的话,会报错

三、为什么需要shadow dom

浏览器的开发者们意识到作为前端开发者,引用一个 <video> 标签的时候,每次还要写入一大堆 DOM 去控制控件的表现和行为,既不简洁也很困难。所以他们界定了这样一个界限,界定了哪些是你可以访问的,哪些实现细节是访问不到的。 那些不希望我们访问到的细节,则封装在了 shadow-dom 中。

如果我们使用了 Shadow DOM,那就可以在它内部随意的发挥,也可以防止样式覆盖的问题

具有良好的密封性

四、shdow dom 的意义

可以将标记结构、样式和行为隐藏起来,并与页面上的其他代码相隔离,保证不同的部分不会混在一起,可使代码更加干净、整洁。

五、和DOM 的关系

Dom:

DOM(Document Object Model)文档对象模型

  • 是一种基于树结构的API 文档,是W3C制定的标准接口规范。
  • 与平台和语言无关。应用于标记文档中(HTML)
    • HTML用来显示页面的内容,css辅助样式位置渲染,js辅助交互。构成网页。
  • DOM 是保存在内存中的树状结构,可以通过动态访问(如JavaScript 来查询或修改其内容)。

DOM分为:

  • HTML DOM
  • XML DOM

shadow DOM始终附加到常规DOM中的元素。没有DOM,shadow DOM就不存在了。

总结:

shdow dom 是什么?其实是浏览器提供的一种封装能力。Shadow DOM 允许将隐藏的 DOM 树附加到常规的 DOM 树中(但是这颗树并不在Dom树中)——它以 shadow root 节点为起始根节点,在这个根节点的下方,可以是任意元素,和普通的 DOM 元素一样。root节点内部具有密封性,会在浏览器中渲染,但是不可见。(当然在谷歌浏览器下的设置下可以配置显示shadow dom。)常规的css选择器不能控制shdow dom tree的样式,但是可以通过伪元素控制。 你可以使用同样的方式来操作 Shadow DOM,就和操作常规 DOM 一样——例如添加子节点、设置属性,以及为节点添加自己的样式(例如通过 element.style 属性)

面试题:

  1. video 的控件是怎么实现的?通过shadow dom 封装技术
  2. dom 是什么? 文档对象模型,一棵树
  3. shadow dom 和dom 的区别 和关系 ?
    • 没有dom 就没有shadow dom,shadow dom 是附加在常规的dom上的
转载自:https://juejin.cn/post/7213935228902621244
评论
请登录