Web Components入门教程示例详解

 更新时间:2023年05月05日 08:55:25   作者:渣渣钱端攻城狮  
这篇文章主要为大家介绍了Web Components入门教程示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

Web Components不兼容IE

2011年提出Web Components,为了解决代码复用问题,早于React、Vue;

相对于React、Vue组件,Web Components是原生组件,不限制接入方的技术,可以接入到React、Vue等技术框架中

困境

  • 兼容性不足,需要主流浏览器的支持,需要平缓的过渡
  • 没有标准的数据绑定机制、在处理自定义元素内部数据、UI更新、组件间参数传递时不够便捷和友好,目前来看大多还依赖于操控dom去实现UI更新

Web Components核心技术

  • 自定义元素
  • HTML模板
  • 影子Dom

自定义元素

使用 window.customElements.define 自定义html标签元素,自定义元素需要我们用JS封装一个,我们在html内使用的自定义元素custom-button就是该类的实例;

自定义标签的生命周期 constructor -> attributeChangedCallback -> connectedCallback

 <!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <custom-button></custom-button>
    <script>
      class CustomButton extends HTMLElement {
        constructor() {
          super();
          console.log("this", this);
          const info = document.createElement("span");
          info.setAttribute("class", "test_custom");
          info.textContent = "自测自定义标签";
          var container = document.createElement("div");
          container.classList.add("container");
          this.append(info, container);
        }
      }
      customElements.define("custom-button", CustomButton);
    </script>
  </body>
</html>

我们可以看到CustomButton继承了HTMLElement,也就是继承了HTML元素的特性,最后我们执行了this.append(DOM),也就是将元素内容添加到当前自定义标签内,this表示自定义元素实例

HTML模板(template、slot)

<template>:包含一个html片段,不会在html初始化时渲染。主要作用是:通过JavaScript获取该代码片段将其放入自定义标签内显示,主要作用于自定义标签

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <template id="test_template">
      <div class="container">
        <span class="test_custom">自测自定义标签</span>
      </div>
    </template>
    <custom-button></custom-button>
    <script>
      class CustomButton extends HTMLElement {
        constructor() {
          super();
          const dom = document.querySelector("#test_template").content;
          this.append(dom);
        }
      }
      customElements.define("custom-button", CustomButton);
    </script>
  </body>
</html>

我们可以发现这种写法相对于前一种方式,更加易读以及便捷

<slot>插槽:给模板元素传值,增强模板元素的灵活性和通用性。 slot在使用过程中具备以下特性

  • 必须在影子Dom种使用,否则不具备插槽的效果
  • 给 Slots 传值的元素必须是自定义元素的直接子元素,否则传值失效
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <template id="test_template">
      <div class="container">
        <span class="test_custom">自测自定义标签</span>
        <slot name="userName" slot="userName"></slot>
      </div>
    </template>
    <custom-button>
      <div class="name_cls" slot="userName">张三</div>
    </custom-button>
    <script>
      class CustomButton extends HTMLElement {
        constructor() {
          super();
          const dom = document.querySelector("#test_template").content;
          this.append(dom);
        }
      }
      customElements.define("custom-button", CustomButton);
    </script>
  </body>
</html>

通过上图发现我们插入的<div class="name_cls">张三</div>并没有插入到container节点内,主要是因为我们的slot没有用在影子dom种,所以浏览器将<div class="name_cls">张三</div>当成其正常的元素进行渲染了;

 <script>
      class CustomButton extends HTMLElement {
        constructor() {
          super();
          const shadow = this.attachShadow({ mode: "closed" });
          const dom = document.querySelector("#test_template").content;
          shadow.append(dom);
        }
      }
      customElements.define("custom-button", CustomButton);
</script>

当我们将slot插入在影子dom,可以发现slot生效了;

另外需要注意的一个点,当使用slot的时候下边这个用法是错误的

// 错误示范
 <custom-button>
     <div> //不能有这一层级
       <div class="name_cls" slot="userName">张三</div>
     </div>
</custom-button>

shadow root(影子Dom)

浏览器提供了一种机制用于隔离一段代码和另一段代码,说到这里你肯定想到iframe,但有时候iframe会显得非常的沉重以及隔离了太多,导致我们使用起来非常的麻烦; 我们可以利用shadow root将CSS和HTML绑定在一起封装成组件,并且其支持天然的样式隔离;

Element.attachShadow()  方法给指定的元素挂载一个 Shadow DOM,并且返回对 ShadowRoot 的引用。

 <script>
      class CustomButton extends HTMLElement {
        constructor() {
          super();
          const shadow = this.attachShadow({ mode: "closed" });
          const dom = document.querySelector("#test_template").content;
          shadow.append(dom);
        }
      }
      customElements.define("custom-button", CustomButton);
</script>

this.attachShadow({ mode: "closed" })closed表示表示 Shadow DOM 是封闭的,不允许外部访问。如果mode的值是open,则表示内部的节点可以被外部访问;

添加样式

  • 如果自定义元素需要样式,我们可以定义全局的样式,例如
custom-button{
  ...
}
  • 正常情况我们应该将样式和自定义标签封装在一起
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div>222</div>
    <template id="test_template">
      <div class="container">
        <span class="test_custom">自测自定义标签</span>
        <slot name="userName"></slot>
      </div>
      <style>
         :host {
          position: relative;
          top: 10px;
        }
        .test_custom {
          color: red;
        }
        div {
          border: 1px solid black;
        }
      </style>
    </template>
    <custom-button>
      <span slot="userName">张三</span>
    </custom-button>
    <script>
      class CustomButton extends HTMLElement {
        constructor() {
          super();
          const shadow = this.attachShadow({ mode: "closed" });
          const dom = document.querySelector("#test_template").content;
          shadow.append(dom);
        }
      }
      customElements.define("custom-button", CustomButton);
    </script>
  </body>
</html>

:host:表示当前的自定义元素节点;

另外可以发现我们定义的div样式只作用于了影子dom内部元素,对于外部的div没有任何影响,证明了影子Dom的样式隔离特性

以上就是Web Components入门教程详解的详细内容,更多关于Web Components入门教程的资料请关注脚本之家其它相关文章!

相关文章

  • 基于JavaScript实现的折半查找算法示例

    基于JavaScript实现的折半查找算法示例

    这篇文章主要介绍了基于JavaScript实现的折半查找算法,结合实例形式分析了折半查找的原理、操作步骤及javascript实现折半查找的相关操作技巧与注意事项,需要的朋友可以参考下
    2017-04-04
  • JavaScript中exec函数用法实例分析

    JavaScript中exec函数用法实例分析

    这篇文章主要介绍了JavaScript中exec函数用法,较为详细的分析了javascript中exec函数的功能、定义及使用方法,需要的朋友可以参考下
    2015-06-06
  • JavaScript实现梯形乘法表的方法

    JavaScript实现梯形乘法表的方法

    这篇文章主要介绍了JavaScript实现梯形乘法表的方法,涉及基本javascript结合表格操作的技巧,需要的朋友可以参考下
    2015-04-04
  • JS获取随机数和时间转换的简单实例

    JS获取随机数和时间转换的简单实例

    下面小编就为大家带来一篇JS获取随机数和时间转换的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-07-07
  • bootstrap栅格系统示例代码分享

    bootstrap栅格系统示例代码分享

    这篇文章主要为大家详细介绍了bootstrap栅格系统示例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • 详解js中的apply与call的用法

    详解js中的apply与call的用法

    在ECAMScript3给Function的原型定义了两个方法,它们是Function.prototype.call和Function.prototype.apply。本文详细介绍了apply与call的用法,有需要的可以参考下。
    2016-07-07
  • js style.display=block显示布局错乱问题的解决方法

    js style.display=block显示布局错乱问题的解决方法

    下面小编就为大家带来一篇js style.display=block显示布局错乱问题的解决方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • JavaScript中的编码和解码函数

    JavaScript中的编码和解码函数

    本文主要介绍了JavaScript中的编码和解码函数。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • 如何在JavaScript中实现私有属性的写类方式(一)

    如何在JavaScript中实现私有属性的写类方式(一)

    这篇文章主要介绍了如何在JavaScript中实现私有属性的写类方式。需要的朋友可以过来参考下,希望对大家有所帮助
    2013-12-12
  • 基于Javascript实现倒计时功能

    基于Javascript实现倒计时功能

    这篇文章主要为大家详细介绍了基于Javascript实现倒计时功能的相关资料,感兴趣的小伙伴们可以参考一下
    2016-02-02

最新评论