Web components - shadow dom 详解
Web平台只提供了一种原生的方法去隔离代码块,iframe,但对大部分需要封装的场景来说,iframe太重而且限制太多。今天介绍的就是另一个技术, 也就是shadow dom(但是浏览器的支持性并不是很好)。
一、在控制台审查元素里显示shdow dom 的步骤
- 测试页面
- 测试浏览器: 谷歌(至于其他浏览器,没有测试)
- 打开控制台,点击右上角设置齿轮icon
- 在设置页面勾选元素里的显示用户代理shdow dom 选项
- 勾选前元素审查只能看到video + source,也无法选中图上的播放键是怎么实现的, 因为对用户来说,这是个黑盒
- 打开shadow dom 配置项后, 可以在控制台看到
#shdow-root(user-agent)
, 展开后,里面就是video 播放键, 音量键, 进度条的具体实现,也可以选中。虽然我们就只有一行的代码,但是也实现了播放暂停音量等控件功能,这都是shadow dom 的功劳。
<video width="320" height="240" controls autoplay>
<source src="movie.ogg" type="video/ogg">
</video>
备注: 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
属性)
面试题:
- video 的控件是怎么实现的?通过shadow dom 封装技术
- dom 是什么? 文档对象模型,一棵树
- shadow dom 和dom 的区别 和关系 ?
- 没有dom 就没有shadow dom,shadow dom 是附加在常规的dom上的
转载自:https://juejin.cn/post/7213935228902621244