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

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

 

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值