前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 shadow DOM [MDN教程]

使用 shadow DOM [MDN教程]

作者头像
Jean
修改2019-05-29 10:30:18
1.7K0
修改2019-05-29 10:30:18
举报
文章被收录于专栏:Web行业观察Web行业观察

原文:https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_shadow_DOM

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

注意: Firefox (从63版本开始),Chrome,Opera 和 Safari默认就支持 Shadow DOM。而 Edge还在实现阶段。

概况

本文章假设你对DOM (文档对象模型) 有一定的了解,它是不同的元素节点、文本节点连接而成的一个树状结构,应用于标记文档中(例如 web文档中经常用到的HTML文档)。请看如下示例,一个 HTML片段:

代码语言:javascript
复制
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Simple DOM example</title>
  </head>
  <body>
      <section>
        <img src="dinosaur.png" alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth.">
        <p>Here we will add a link to the <a href="https://www.mozilla.org/">Mozilla homepage</a></p>
      </section>
  </body>
</html>

这个片段会生成如下 DOM结构:

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

需要了解的 Shadow DOM相关技术:

  • Shadow host: 一个常规 DOM节点,Shadow DOM会被添加到这个节点上。
  • Shadow tree:Shadow DOM内部的DOM树。
  • Shadow boundary:Shadow DOM结束的地方,也是常规 DOM开始的地方。
  • Shadow root: Shadow tree的根节点。

你可以使用同样的方式来操作Shadow DOM,就和操作常规DOM一样——例如添加子节点、设置属性,以及为节点添加自己的样式(例如通过 element.style.foo属性),或者为整个 Shadow DOM添加样式(例如在<style> 元素内添加样式)。不同的是,Shadow DOM内部的元素始终不会影响到它外部的元素,这为封装提供了便利。

注意,不管从哪个方面来看,Shadow DOM 都不是一个新事物——在过去的很长一段时间里,浏览器用它来封装一个元素的内部结构。以一个有着默认播放控制按钮的<video>元素为例。你所能看到的只是一个 <video>标签,实际上,在它的Shadow DOM中,包含来一系列的按钮和其他控制器。Shadow DOM标准允许你为你自己的元素(custom element)维护一组 Shadow DOM。

基本用法

可以使用Element.attachShadow() 方法来将一个 shadow root 附加到任何一个元素上。它接受一个配置对象作为参数,该对象有一个mode属性,值可以是open或者closed

代码语言:javascript
复制
let shadow = elementRef.attachShadow({mode: 'open'});
let shadow = elementRef.attachShadow({mode: 'closed'});

open 表示你可以通过页面内的 JavaScript 方法来获取 Shadow DOM,例如使用Element.shadowRoot 属性:

代码语言:javascript
复制
let myShadowDom = myCustomElem.shadowRoot;

如果你将一个 Shadow root 添加到一个 Custom element 上,并且将 mode设置为closed,那么就不可以在外部获取 Shadow DOM了——myCustomElem.shadowRoot 将会返回 null。浏览器中的某些内置元素就是这样的,例如<video>,包含了不可访问的 Shadow DOM。

注意: 正如这篇文章所阐述的,处理 closed Shadow DOMs 实际上很简单,往往也很值得这么做。

如果你想将一个Shadow DOM添加到 custom element上,可以在 custom element的构造函数添加如下实现(这往往也是最有用的做法):

代码语言:javascript
复制
let shadow = this.attachShadow({mode: 'open'});

当你将一个 Shadow DOM添加到一个元素上,那么之后,就可以使用 DOM APIs 对它进行操作,就和处理常规DOM一样。

代码语言:javascript
复制
var para = document.createElement('p');
shadow.appendChild(para);
etc.

编写简单示例

现在,让我们着手实现一个示例——<popup-info-box>(也可以查看在线示例),来说明 Shadow DOM在 custom element 中的实际运用。它包含一个图片 icon和一段文字,这个图片 icon用于在页面上显示。每当 icon获取到焦点时,文字会在一个弹框中显示,以提供更加详细的信息。首先,在 JavaScript文件中,我们需要定义一个叫做 PopUpInfo的类,它继承自HTMLElement

代码语言:javascript
复制
class PopUpInfo extends HTMLElement {
  constructor() {
    // 必须首先调用 super方法
    super();

    // 元素的具体功能写在下面

    ...
  }
}

在上面的类中,我们将会在它的构造函数中定义元素所有的功能。当类实例化后,所有的实例元素都会有相同功能。

创建 shadow root

在构造函数中,我们首先将 Shadow root 添加到 custom element上:

代码语言:javascript
复制
// 创建 shadow root
var shadow = this.attachShadow({mode: 'open'});

创建 shadow DOM 结构

接下来,我们会使用相关DOM 操作来创建元素的 Shadow DOM结构:

代码语言:javascript
复制
// 创建 span
var wrapper = document.createElement('span');
wrapper.setAttribute('class','wrapper');
var icon = document.createElement('span');
icon.setAttribute('class','icon');
icon.setAttribute('tabindex', 0);
var info = document.createElement('span');
info.setAttribute('class','info');

// 获取属性的内容并将内容添加到 info元素内
var text = this.getAttribute('text');
info.textContent = text;

// 插入 icon
var imgUrl;
if(this.hasAttribute('img')) {
  imgUrl = this.getAttribute('img');
} else {
  imgUrl = 'img/default.png';
}
var img = document.createElement('img');
img.src = imgUrl;
icon.appendChild(img);

为 shadow DOM 添加样式

之后,我们将要创建<style>元素,并加入一些 CSS样式:

代码语言:javascript
复制
// 为 shadow dom添加一些 CSS样式
const style = document.createElement('style');

style.textContent = `
                          .wrapper { 
                            position: relative;
                          }

                          .info {
                            font-size: 0.8rem;
                            width: 200px;
                            display: inline-block;
                            border: 1px solid black;
                            padding: 10px;
                            background: white;
                            border-radius: 10px;
                            opacity: 0;
                            transition: 0.6s all;
                            position: absolute;
                            bottom: 20px;
                            left: 10px;
                            z-index: 3;
                          }

                          img {
                            width: 1.2rem;
                          }

                          .icon:hover + .info, 
                          .icon:focus + .info {
                            opacity: 1;
                          } `;

将 Shadow DOM添加到 Shadow root上

最后,将所有创建的元素添加到 Shadow root上:

代码语言:javascript
复制
// 将所创建的元素添加到 Shadow DOM上
shadow.appendChild(style);
shadow.appendChild(wrapper);
wrapper.appendChild(icon);
wrapper.appendChild(info);

使用我们的 custom element

完成类的定义之后,使用元素也是同样的简单,只需将 custom element放在页面上,正如Using custom elements中讲解的那样:

代码语言:javascript
复制
// 定义新的元素
customElements.define('popup-info', PopUpInfo);
代码语言:javascript
复制
<popup-info img="img/alt.png" text="Your card validation code (CVC) is an extra 
                                    security feature — it is the last 3 or 4
                                    numbers on the back of your card.">

效果


文档标签和贡献者

此页面的贡献者: mdnwebdocs-bot, Louis-7, haoliangwu, zhang-quan-yi

最后编辑者: mdnwebdocs-bot, Mar 18, 2019, 5:35:29 PM

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概况
  • 基本用法
  • 编写简单示例
    • 创建 shadow root
      • 创建 shadow DOM 结构
        • 为 shadow DOM 添加样式
          • 将 Shadow DOM添加到 Shadow root上
            • 使用我们的 custom element
            • 效果
            • 文档标签和贡献者
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档