初识 shadowDOM (学习笔记)

当下的前端界,各种MV*框架大行其道,而在这之前则是jQuery一家独大。jQuery是操作dom的利器,并且将dom封装成了JQ对象从而增加了一些新的api及特性。而MV*们则更加的“粗暴”,直接屏蔽了底层的dom操作,直接通过框架将数据映射到模板上。不仅如此,MV*们更是为中大型项目的组织构建提供了良好的基础——模块抽离和代码复用。

无论是vue等还是各家的小程序,都提供了templateslot ,其主要的作用是将一部分逻辑相似的代码进行复用,同时也允许在复用的时候提供一些定制化配置。

抛掉这些,我们的原生html是否提供了类似的功能?


shadowDOM的介绍

Web components的一个重要特性是封装——可以将html标签结构、css样式和行为隐藏起来,并从页面上的其他代码中分离开来,这样不同的功能不会混在一起,代码看起来也会更加干净整洁。其中,shadowDOM接口是关键所在,它可以将一个隐藏的、独立的DOM添加到一个元素上。

shadowDOM, 顾名思义,影子节点。影子节点需要依附在一个宿主节点上,并且也会将宿主节点中的内容给替换掉(注意这里是 替换 而不是 添加)。同时在影子节点内部是一个独立的作用域,并不会受外部的样式影响。

shadowDOM的用法

<head> 
  .....  
  <style>    
    p {
      color: yellowgreen;
    }  
  </style>
</head>

<body>
  <div id="host" >
    这里是shadowROM的宿主
  </div>

  <p>这里是shadowRoot外面的内容</p>
</body>复制代码

创建一个template ,同时给这个template中的p标签设定新的样式

  <template id="shadowContent" >
    <style>
      p {
        color: red;
      }
    </style>
    <p>这里是template中的内容</p>
  </template>复制代码

host.attachShadow({mode: 'open'}) 可以给host节点依附一个shadowDOM,并且返回这个有的shadowDOM节点。

document.querySelector('#shadowContent').content 中的 contenttemplate 的特有属性

最后将克隆的节点添加到shadowDOM下。

  <script>
    let host = document.querySelector('#host')
    let shadowRoot = host.attachShadow({mode: 'open'})

    let shadowContent = document.querySelector('#shadowContent').content.cloneNode(true)

    shadowRoot.appendChild(shadowContent)
  </script>复制代码

最终的效果:



在上图中,我们可以看到template模板,是作为一个document-fragment 存在的。这表明它是存在于内存中而不是主dom树上,它并不会因为template 中的内容变化而引起文档的reflow。

配合slot使用

直接上代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>测试shadowDOM</title>
  <style>
    p {
      color: yellowgreen;
    }
  </style>
</head>
<body>
  <div id="host" >
    <p slot="slot1" >我是要放到占位符里的内容</p>
    这里是shadowROM的宿主
  </div>

  <p>这里是shadowRoot外面的内容</p>

  <!-- 以下为模板相关 -->
  <template id="shadowContent" >
    <style>
      p {
        color: red;
      }
    </style>
    <!-- 以下是一个占位符 -->
    <slot name="slot1" ></slot>
    <p>这里是template中的内容</p>
  </template>

  <script>
    let host = document.querySelector('#host')
    let shadowRoot = host.attachShadow({mode: 'open'})

    let shadowContent = document.querySelector('#shadowContent').content.cloneNode(true)

    shadowRoot.appendChild(shadowContent)
  </script>
 </body>
</html>复制代码

效果:


值得注意的是slot的样式是文档中的样式,而不是template中的样式

结尾

其实shadowDOM已经被大家所广泛使用,最常见的就是一些视频播放网站的定制的video标签就是利用了shadowDOM

最后,新手上路,如有争议,欢迎讨论。


转载于:https://juejin.im/post/5c2ec1bd6fb9a049e66060f5

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值