相信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