【前端帮帮忙】第2期 Shadow DOM来了解一下

本文深入解析ShadowDOM的概念,探讨其在Web组件中的作用及浏览器对其的封装机制。文章讲解了如何控制ShadowDOM,包括通过CSS伪元素修改样式,以及如何利用Element.attachShadow()创建自定义ShadowDOM。

Shadow DOM是什么

顾名思义,即影子DOM,看不见摸不着,我们无法直接控制操纵的DOM结构。

Mozilla对其的描述,点击查看

Shadow DOM 为Web组件中的 DOM和 CSS提供了封装。Shadow DOM 使得这些东西与主文档的DOM保持分离。你也可以在一个Web组件外部使用 Shadow DOM本身。

来看下W3CShadow DOM的描述:

  • A shadow host is an element that hosts one or more node trees.
  • A shadow tree is a node tree hosted by a shadow host.
  • A shadow root is the root node of a shadow tree.

这三句话告诉我们:

  • shadow dom 由一颗或多颗 shadow tree 组成,并且需要一个普通的dom元素作为它的容器
  • shadow tree 是一颗节点树
  • shadow root 是shadow tree的根节点

简单理解

我们来写一个小例子来加深对其的理解,写一个简单的滑块标签

<input type="range">
复制代码

然后在Chrome浏览器按F12打开开发者工具,再按F1打开设置项,找到Show user agent shadow DOM并把其勾选上。

切换到Elements,我们发现input标签下多了#showdow-root (user agent)这个东西,它包含了input控件内部的DOM结构,这就是所谓的Shadow DOM了。

为什么我们只写了一个input标签,会多出这么多东西呢?实际上就是浏览器自动帮我们加上的,只不过通过某种技术隐藏了起来而已。

那浏览器为什么要这么做呢?很明显就是让我们写代码的时候更简单,我们可以再写一个标签来测试一下:

<video controls="controls" autoplay="autoplay">
  <source src="http://www.w3school.com.cn/i/movie.ogg" type="video/ogg" />
  <source src="http://www.w3school.com.cn/i/movie.ogg" type="video/mp4" />
Your browser does not support the video tag.
</video>
复制代码

你会发现多了太多的代码了,所以,实际上是浏览器对某些复杂的标签做了一层类似组件的封装,把我们可能无需关心的部分隐藏起来了,这样,我们使用的时候就可以少写很多代码。

如何控制Shadow DOM?

既然是浏览器有意隐藏起来的DOM结构,那我们是否可以控制内部的DOM结构呢?并非完全不可以,我们会发现上面滑块的Shadow DOM里有pseudo这样的属性

<div pseudo="-webkit-slider-runnable-track" id="track"></div>
复制代码

因此我们可以通过CSS伪元素选中该元素,然后修改它的样式:

input::-webkit-slider-runnable-track {
    background-color: red;
}
复制代码

可以发现整个滑块背景都变成了红色。虽然这并不是我们想要的效果,但这确实是Shadow DOM开放给我们选择的。

不幸的是,虽然很多浏览器都支持Shadow DOM,但目前只有Chrome浏览器支持对其审查和附加选择器。

Shadow DOM的兼容性

我们可以在caniuse.com查看, 查看地址

如何创建一个Shadow DOM元素?

除了原生的Shadow DOM,我们可不可以闯将自己的呢?

Shadow DOM必须附加在一个元素上,可以是HTML文件中的一个元素,也可以是脚本中创建的元素;可以是原生的元素,如<div><p>;也可以是自定义元素如<my-element>

其实有这样一组API来实现的,通过Element.attachShadow()方法来为元素附加一个Shadow DOM。来看个例子:

<div id="sd-box"></div>
复制代码
var shadow = document.querySelector('#sd-box').attachShadow({
   mode: 'open' 
});
复制代码

这里的mode用来指定Shadow DOM封装的模式,可取值有:

  • open:开放的封装模式
  • closed:关闭的封装模式

这时候,页面上并没有什么变化,继续添加下面的代码:

shadow.innerHTML = '<p>this is Shadow DOM</p>';
复制代码

可以看到页面出现上面的文本,该标签的结构变成了

<div id="sd-box">
  #shadow-root (open)
  <p>this is shadow DOM</p>
</div>
复制代码

证明我们确实是通过attachShadow()方法成功为某个元素创建了Shadow DOM。

如果想为其添加样式,可以通过下面的方式来实现:

shadow.innerHTML += '<style>p { color: red; }</style>'
复制代码

可以发现,页面上该标签的字体变成了红色。

Shadow DOM API其实是Web Components的一部分,用来封装组件的DOM和CSS,区别于Vue.js这样的组件化框架,Web Components是浏览器原生的组件化方式,不过目前还处于初期,只有Chrome和Safari极少数浏览器支持。

参考

developer.mozilla.org/zh-CN/docs/…

www.cnblogs.com/WhiteCusp/p…

blog.youkuaiyun.com/u012207345/…

由于我水平、文笔有限,如果各位在文章中发现有任何不合理,不正确的地方,还烦不吝指出,我会非常感谢的;如果通过文章有任何想法或疑问,也希望各位能积极留言,我们互相交流探讨;如果通过本文章能让你有所收获,可以分享出去,让更多的人受益。

欢迎大家关注我的公众号,前端路上一起学习成长,感谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值