web Components---shadow DOM

一、Shadow DOM简介

Shadow DOM能够将一个隐藏的、独立的DOM附加到一个元素上。它可以保证元素功能的私有,这样就可以作为一个组件被其他页面引用,而不与外部发生冲突。

题外话:Shadow DOM对我们来说其实并不陌生,浏览器很久以前就在用它封装元素内部结构。

如何查看:
第一步:在页面内写入一个input标签一个video标签
第二步:通过浏览器打开
第三步:(按F12)打开开发者工具进行如下设置

就能够发现原来这些标签的内部乾坤就是用Shadow DOM来实现的👍

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、Shadow DOM与DOM树

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

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

三、在Web Components中的基本用法

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

let shadow = elementRef.attachShadow({mode: 'open'});
let shadow = elementRef.attachShadow({mode: 'closed'});
// 将Shadow DOM附加到custom element上,可以在custom element的构造函数中添加如下代码(shadow DOM最实用的用法)
let shadow = this.attachShadow({mode: 'open'});
  • open 表示可以通过页面内的 JavaScript 方法来获取 Shadow DOM。

  • closed表示不可以从外部获取,浏览器中的某些内置元素就是如此。

    通过js方法获取 Shadow DOM
    let myShadowDom = myCustomElem.shadowRoot;

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

基本使用示例:
let shadow = this.attachShadow({mode: 'open'});
var para = document.createElement('p');
shadow.appendChild(para);

四、使用Web Components和shadow dom实现简单功能

实现一个鼠标滑过图标展示提示信息的功能
效果: ↓↓↓

在这里插入图片描述
在这里插入图片描述

// 1. 定义继承自HTMLElement的PopPopUpInfo类
class PopUpInfo extends HTMLElement {
  // 2. 在构造函数中定义元素所有功能
  constructor() {
    // 3. 必须首先调用 super方法
    super();
    // 4. 创建shadow root
    var shadow = this.attachShadow({ mode: "open" });

    // 5. 创建 shadow DOM 结构
    // 5.1 创建 span
    var wrapper = document.createElement("span");
    wrapper.setAttribute("class", "wrapper");
    var icon = document.createElement("div");
    icon.setAttribute("class", "icon");
    icon.innerText = "?";
    var info = document.createElement("span");
    info.setAttribute("class", "info");
    // 5.2 获取属性的内容并将内容添加到 info 元素内
    var text = this.getAttribute("text");
    info.textContent = text;

    // 6. 为 shadow DOM 添加一些 CSS 样式
    var 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: 6px;
        left: 16px;
        z-index: 3;
        }
        .icon {
            width: 20px;
            height: 20px;
            margin-top: 100px;
            background-color: #888;
            border-radius: 10px;
            text-align: center;
            color: #FFF;
        }
        .icon:hover + .info {
        opacity: 1;
        }
    `;
    // 7. 将所创建的元素添加到 Shadow DOM 上
    shadow.appendChild(style);
    shadow.appendChild(wrapper);
    wrapper.appendChild(icon);
    wrapper.appendChild(info);
  }
}
// 8. 定义新的元素
customElements.define("popup-info", PopUpInfo);
对上述代码进行优化:
  1. 简化定义过程,将class popupInfo extends HTMLElement{...}customElements.define("popup-info", popupInfo)合并为:

    customElements.define(
      "popup-info",
      class extends HTMLElement {...})
    
  2. 将通过document.createElementsetAttributeappendChild等实现的css样式及html结构,改为直接通过html格式书写,语义性更强,更符合书写习惯。

// 1. 简化定义过程
customElements.define(
  "popup-info",
  class extends HTMLElement {
    // 2. 在构造函数中定义元素所有功能
    constructor() {
      // 3. 必须首先调用 super方法
      super();
      // 4. 创建shadow root
      const shadow = this.attachShadow({ mode: "open" });

      // 5. 通过innerHTML形式,创建 shadow DOM 结构
      let htmlStr = `
        <style>
            .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: 6px;
            left: 16px;
            z-index: 3;
            }
            .icon {
                width: 20px;
                height: 20px;
                margin-top: 100px;
                background-color: #888;
                border-radius: 10px;
                text-align: center;
                color: #FFF;
            }
            .icon:hover + .info {
            opacity: 1;
            }
        </style>
        <span class="wrapper" id="wrapper">
        <div class="icon">?</div>
        <span class="info" id="info"></span>
        </span>
    `;

      // 6. 将创建的Shadow DOM添加到shadow root上
      shadow.innerHTML = htmlStr;

      // 7. 获取属性的内容并将内容添加到 info 元素内
      /* 注意!!采用此种注册形式时一定要在加载完html后
         才能通过shadowRoot获取元素并进行操作 */
      var text = this.getAttribute("text");
      let info = this.shadowRoot.children.wrapper.children.info;
      info.innerHTML = text;
    }
  }
);

五、参考链接

MDN: Web Components:https://developer.mozilla.org/zh-CN/docs/Web/Web_Components

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值