首页 > 其他分享 >究竟什么是Shadow DOM?

究竟什么是Shadow DOM?

时间:2023-02-02 10:11:06浏览次数:39  
标签:DOM const dom 元素 Shadow root shadow 究竟

shadow dom 是什么?

顾名思义,shadow dom直译的话就是影子dom,但我更愿把它理解为DOM中的DOM。因为他能够为Web组件中的 DOM和 CSS提供了封装,实际上是在浏览器渲染文档的时候会给指定的DOM结构插入编写好的DOM元素,但是插入的Shadow DOM 会与主文档的DOM保持分离,也就是说Shadow DOM不存在于主DOM树上。

并且Shadow DOM封装出来的DOM元素是独立的,外部的配置不会影响到内部,内部的配置也不会影响外部。

如果这篇文章有帮助到你,❤️关注+点赞❤️鼓励一下作者,文章公众号首发,关注 前端南玖 第一时间获取最新文章~

思考

理解完它的概念,我们再来思考一个问题:

为什么我们用的一些标签明明就是一个空元素,但他却能够渲染出各种复杂的场景?

  • input
  • video
  • audio
  • textarea
  • 等...

可能很多同学都没想过为什么这些标签跟我们常用的div标签不一样,它们就简单写个标签就能渲染出对应的样式与功能;

或者有些同学理解成这都是底层渲染的事,我们不必关心。

ydl.gif

是的,这些标签内部的内容确实都是底层渲染的,不过我们也不是看不到它们内部的实现原理。

查看html原生标签的Shadow DOM

在html中写入以下标签,然后到浏览器控制台去查看

<input type="text">
<input type="range">
<video src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4" controls></video>
<textarea></textarea>

1.png

很多人看到的是这样的,但这和我们写的没有任何区别呀?别急,这就带你看看他们的真实面目~

首先打开浏览器控制台的设置选项

2.png

然后再找到Preference -> Elements,把show user anent shadow dom勾上

3.png

这时候我们再来看一下此时的dom元素发生了什么变化

4.png

我们会发现这些标签内部都大有乾坤,在这些标签下面都多了一个shadow root,在它里面才是这些标签的真实布局。

既然这些标签内部都有一些子元素布局,那么我们能不能通过JavaScript来访问到它们呢?

const input = document.querySelector('input')
console.log(input.firstChild)  // null

很明显,这是不可以的!

因为它为web开发者设定了一个边界,界定了哪些是你可以访问的,哪些实现细节是访问不到的。然而,浏览器本身却可以随意跨越这个边界。设置这样一个边界之后,它们就可以在你看不见的地方使用熟悉的web技术、同样的HTML元素去创建更多的功能,而不是像你一样要在页面上用div和span来堆。

shadow dom 结构

Shadow DOM 允许将隐藏的 DOM 树附加到常规的 DOM 树中——它以 shadow root 节点为起始根节点,在这个根节点的下方,可以是任意元素,和普通的 DOM 元素一样。

就是因为这个特点所以我们才能看到上面那些单个空标签就能够渲染出各种各样的复杂场景。

shadowdom.png

上面这张图非常直观的表现了shadow dom的结构以及它与真实dom的关系。

shadow host

一个常规 DOM 节点,Shadow DOM 会被附加到这个节点上。

shadow bounday

Shadow DOM 结束的地方,也是常规 DOM 开始的地方。

shadow tree

Shadow DOM 内部的 DOM 树。

shadow root

Shadow tree 的根节点。

如何使用shadow dom?

创建一个shadow dom

我们可以使用attachShadow给指定元素挂载一个shadow dom,并且返回对shadow root的引用。

const shadowroot = root.attachShadow({mode: 'open'})
const template = `
  <div>前端南玖</div>
 `
shadowroot.innerHTML = template

shadow dom mode

当调用Element.attachShadow()方法t时,必须通过传递一个对象作为参数来指定shadow DOM树的封装模式,否则将会抛出一个TypeError。该对象必须具有mode属性,值为 openclosed

  • open shadow root 元素可以从 js 外部访问根节点,例如使用 Element.shadowRoot:
element.shadowRoot; // 返回一个 ShadowRoot 对象
  • closed 拒绝从 js 外部访问关闭的 shadow root 节点
element.shadowRoot; // 返回 null

浏览器通常用关闭的 shadow roo 来使某些元素的实现内部不可访问,而且不可从JavaScript更改。

对于一些不希望公开shadow root 的Web组件来说,封闭的shadow DOM看起来非常方便,然而在实践中绕过封闭的shadow DOM并不难。但是完全隐藏shadow DOM所需的工作量也大大超过了它的价值。

哪些元素可以挂载shadow dom?

这里需要注意的是并非所有html元素都可以挂载shadow dom,只有以下这些元素可以充当shadow dom的 shadow host

articleasideblockquotebody
div footer h1 h2
h3 h4 h5 h6
header main nav p
section span 任何带有有效的名称且可独立存在的自定义元素  

当我们尝试在其它元素挂在shadow dom时,浏览器则会抛出异常。

const input = document.querySelector('input')
const inputRoot = input.attachShadow({mode: 'open'})

5.png

shadow dom的特点

从前面的介绍,我们知道shadow dom是游离在 DOM 树之外的节点树,但是它是基于普通 DOM 元素(非 document)创建的,并且创建后的 Shadow-dom 节点可以从界面上直观的看到。最重要的一点是Shadow-dom 具有良好的密封性。

样式

<style>
  .wx_name {
    color:aqua;
  }
</style>
<body>
    <div class="wx_name">我是真实dom</div>
    <div id="root"></div>

    <script>
        const shadowroot = root.attachShadow({mode: 'open'})
        const template = `
            <div class="wx_name">shadow dom - 前端南玖</div>
        `
        shadowroot.innerHTML = template
    </script>
</body>

它渲染出来是下面这样的

标签:DOM,const,dom,元素,Shadow,root,shadow,究竟
From: https://www.cnblogs.com/mq0036/p/17085050.html

相关文章

  • 数据仓库、数据湖、湖仓一体,究竟有什么区别
    数据,已经成为了企业的生命线与核心资产,数据管理和数据分析成为非常重要的应用领域。出于对数据管理领域的关注,不同行业也逐步提升了对数据存储、数据治理及数据分析能力的......
  • 路由react-router-dom的使用
    react-router-dom路由简介现代的前端页面大多是SPA(单页面应用程序),也就是只有一个HTML页面的程序,这样用户体验好,服务器压力小,所以更受欢迎。路由是使用单页面来管理原来......
  • jsDOM操作之获取元素
    1 根据id名获取document.getElementById(idName)2根据标签名获取document.getElementsByTagName(tagName)//返回一个集合(类数组对象)从整个文档获取element.getElem......
  • js之DOM简介
    1什么是DOM1)DOM英文全称“DocumentObjectModel”,译为“文档对象模型”。2)DOM是一个与平台和编程语言无关的接口,通过这个接口程序和脚本可以动态的访问和修改文档的内......
  • DOM属性操作中CRUD操作
    CRUD操作1.append():父元素将子元素追加到末尾对象1.append(对象2):将对象2添加到对象1元素内部,并且在末尾2.prepend():父元素将子元素追加到开头对象1.appen......
  • JavaScript学习笔记—DOM:事件
    事件(event)事件就是用户和页面之间发生的交互行为比如:点击按钮,鼠标移动,双击按钮,敲击键盘,松开按键...可以通过为事件绑定响应函数(回调函数),来完成和用户之间的交互绑定响......
  • DOM的通用属性和class属性操作
    DOM的通用属性attr():获取/设置元素的属性removeAttr():删除属性prop():获取/设置元素的属性removeProp():删除属性attr和prop区别:1、如果操作的是元素的固有属性,则......
  • Domain Driven Design浅解
    DomainDrivenDesignDDD是domaindrivendesign的缩写,中文是领域驱动设计,是由EricEvans提出的一种架构思想。中文定义:领域驱动设计是一种处理高度复杂领域的设......
  • JavaScript学习笔记—DOM:属性节点
    属性也是一个节点对象(Attr),和文本一样,通常我们不会去直接获取节点对象,而是通过元素来完成对属性的操作:方式一:读取:元素.属性名(注意,class属性需要使用className来读取)读......
  • javascript:js 读写 style属性(DOM模型)
    javascript:js读写style属性(DOM模型)    一、说明: 1、js读取style属性,需要去掉css格式中的“-”,“-”后面的第一个字母大写。js中的减号(“-”),与css中属性......