shadow dom的作用和用法详解(createShadowRoot, attachShadow)

mac2022-10-03  30

相信shadow dom很多前端开发工作者都遇到过,它是web component的一部分。不过对于shadow dom很多人并不深入了解,只晓得是影子dom结构,那么到底什么是shadow dom的,本文将从概念,作用,用法三个方面来介绍下shadow dom.

介绍shadow dom之前,首先看几个常用的标签,例子1:

<video controls autoplay name="media"> <source id="mp4" src="http://media.w3.org/2010/05/sintel/trailer.mp4" type="video/mp4"> </video> <-- 实际显示 --> <video src="a.mp4" width="480" height="360"> #shadow root <div pseudo="-webkit-media-controls"> <div pseudo="-webkit-media-controls-overlay-enclosure"> <input type="button" style="display: none;"> </div> <div pseudo="-webkit-media-controls-enclosure"> <div pseudo="-webkit-media-controls-panel" style="display: none;"> <input type="button" pseudo="-webkit-media-controls-play-button"> <input type="range" step="any" pseudo="-webkit-media-controls-timeline" max="0"> <div pseudo="-webkit-media-controls-current-time-display" style="display: none;">0:00</div> <div pseudo="-webkit-media-controls-time-remaining-display">0:00</div> <input type="button" pseudo="-webkit-media-controls-mute-button"> <input type="range" step="any" max="1" pseudo="-webkit-media-controls-volume-slider" style="display: none;"> <input type="button" pseudo="-webkit-media-controls-toggle-closed-captions-button" style="display: none;"> <input type="button" style="display: none;"> <input type="button" pseudo="-webkit-media-controls-fullscreen-button" style="display: none;"> </div> </div> </div> </video>

video标签就是shadow dom结果,从上述代码可以看出,在渲染之后,显示了很多内部封装的结构。

<input type="range"> ,<audio></audio>也是shadow dom结构。

shadow概念:

Shadow DOM 是一个 HTML 的规范,其允许开发者封装自己的 HTML 标签、CSS 样式和 JavaScript代码。

shadow功能:

既然是封装html片段,那么功能显而易见,就是让开发人员可以创建出诸如 video这样自定义的一级标签,并且Shadow-dom 具有良好的密封性,方便复用。

Shadow-dom 是游离在 DOM 树之外的节点树,Shadow-dom 具有良好的密封性

shadow-dom Api详解

先来一段html, 以下操作基于该html

<body> <div id="notificaton"> <p>createShadowRoot</p> <button>学习</button> </div> <div id="notificatonNew"> <p>attachShadow</p> <button>学习</button> <span slot="main1" class = "slot-test"> 插槽1 </span> <span slot="main2"> 插槽2 </span> <template id="tpl"> <style> span { color:red; } </style> <!-- 这里将显示影子根节点中定义的插槽内容 --> <slot name="main1"></slot> <slot name="main2"></slot> <span>hello world</span> </template> </div> </body>

1,老api  createShadowRoot

//创建shadow后,notificaton元素及子节点内容不可见 const shadow = document.getElementById('notificaton').createShadowRoot();

2,新的api attachShadow

const notificatonNew = document.getElementById('notificatonNew'); const shadowroot = notificatonNew.attachShadow({mode:'open'});

说明:attachShadow参数含义

mode: 一个指定Shadow DOM封装模式的字符串,可以是下列之一: open 指定为开放的封装模式。closed 指定为关闭的封装模式。

给影子dom添加内容:

通过innerHTML添加:

shadow.innerHTML = ` <style>:host { font-weight: bold; color:blue; }</style> <p class = "shadow-inside-node">Lorem ipsum dolor sit amet.</p> <content select="span"> Lorem ipsum dolor sit amet. <div>test-div</div> </content> `

说明://:host 伪选择器,通过 :host 可以选择 shadow

通过模板添加:

//'tpl'是上面template的id shadowroot.appendChild(document.getElementById('tpl').content.cloneNode(true));

扩展功能:插槽slot的使用

shadow中可以使用插槽,在要创建shadow dom的元素内先定义好插槽,然后在模板中使用插槽,渲染时会替换插槽。

shadowroot.innerHTML = ` <style> :host { color: blue; } </style> <slot name="main1"></slot> <slot name="main2"></slot> <slot> `

在模板中使用

<div id="notificatonNew"> <p>attachShadow</p> <button>学习</button> <span slot="main1" class = "slot-test"> 插槽1 </span> <span slot="main2"> 插槽2 </span> <template id="tpl"> <style> span { color:red; } </style> <!-- 这里将显示影子根节点中定义的插槽内容 --> <slot name="main1"></slot> <slot name="main2"></slot> <span>hello world</span> </template> </div>

slot属于较新的api,存在兼容性问题,尽量不要在生产环境使用

参考:https://www.imweb.io/topic/5593cc62799539f821cd2541

https://blog.csdn.net/Aijn_faluts/article/details/88658884

https://www.cnblogs.com/yangguoe/p/8486046.html

https://www.jianshu.com/p/9293cac60920

https://developer.mozilla.org/zh-CN/docs/Web/API/Element/attachShadow

 

最新回复(0)