Web Component 快速入门

什么是 Web Component

Web Component 是一种 W3C标准 支持的 组件化方案,经过它,咱们能够编写可复用的 组件,同时,咱们也能够对本身的组件作更精细化的控制。正如 PWA 同样,他并不是一项单一的技术,而是由三项技术组成javascript

  1. Shadow DOM
  2. Custom elements
  3. HTML templates

下面,咱们从一个简单的例子来入手。css

从一个例子提及

咱们准备编写一个 TextReverse 组件,TextReverse 只有一个很简单的功能,就是把传入的 字符串颠倒显示html

例如: <text-reverse text='123'></text-reverse> 将会显示 321java

第一步,咱们须要 定义 这个自定义组件。浏览器

class TextReverse extends HTMLElement {
    constructor() {
        super();
        const shadowRoot = this.attachShadow({ mode: 'open' });
        const text = this.getAttribute('text') || '';
        const wrapper = document.createElement('span');
        wrapper.textContent = text.split('').reverse().join('');
        shadowRoot.appendChild(wrapper);
    }
}
复制代码

定义组件的方式也十分简单,咱们只须要 继承一下 HTMLElement,而后在 构造函数 中编写本身的 初始化逻辑 就能够了。app

初始化过程当中,咱们首先 建立了一个 shadowRoot,这个至关因而咱们整个组件的一个 根结点框架

紧接着,咱们获取到自身的 text 属性,而且将其 倒置 放入新建立的 span 元素中。dom

最后,咱们把带有 textspan 塞入 shadowRoot函数

定义完成以后,咱们要告知一下系统,也就是 组件注册组件化

customElements.define(
    'text-reverse',
    TextReverse
)
复制代码

这里有一个小细节,就是咱们注册的名字必须是带短横线的。

注册完成以后就能够正式使用啦。

<text-reverse text='12345'></text-reverse>
复制代码

Shadow Dom

上面的例子中,咱们用到了 shadow root他承载着咱们组件全部的内容。而他也是 Web Component 核心技术。

咱们都知道 Dom 其实就是一棵树,而咱们的组件则是树上的一个节点。咱们能够称组件节点为 shadow host

shadow host 中含有一颗与外界隔离的 dom 树,咱们称之为 shadow tree。shadow tree 中的内容不会影响到外界。Shadow Root 则是这一课shadow tree 的根节点。

结构如图所示:

样式隔离

shadow dom 一大亮点就是样式隔离。咱们能够给以前的例子加上样式。

class TextReverse extends HTMLElement {
    constructor() {
        super();
        // ...
        const style = document.createElement('style');
        style.textContent = `* { background: red; }`
        shadowRoot.appendChild(style);
        // ...
    }
}

复制代码

咱们给全部元素添加一个红的背景色。可是,结果只有组件内的元素背景色受到了影响。这种样式隔离的特性很好地避免了不一样组件之间的样式干扰。

Template

在上面的例子中,咱们采用代码的方式来建立修改节点。相较于 React 的 Jsx 和 Vue 的模版,这种方法比较低效。因此,咱们可使用 Template 来解决这问题。

<template id='text-reverse'>
    <style> *{ background: red; } </style>
    <span id='text'></span>
</template>
复制代码
class TextReverse extends HTMLElement {
    constructor() {
        super();
        const shadowRoot = this.attachShadow({ mode: 'open' });
        const text = this.getAttribute('text') || '';
        const template = document.getElementById('text-reverse').content.cloneNode(true);
        template.getElementById('text').textContent = text.split('').reverse().join('');
        shadowRoot.appendChild(template);
    }
}
复制代码

咱们在 html 中定义了一个 template,而后,就和操做普通元素同样获取到 template 节点,而后深拷贝一份节点内容。最后直接操做这个节点。

Slot

VueSlot 类似,Slot 赋予了组件更高的可扩展性。经过 Slot,咱们能够给组件传入更多的自定义内容。

在上面的例子中,咱们给组件添加一个自定义的标题。

<text-reverse text='12345'>
    <span slot='title'>text reverse</span>
</text-reverse>
<template id='text-reverse'>
        <h1><slot name='title'>default title</slot></h1>
        <span id='text'></span>
</template>
复制代码

模版中,咱们定义一个 slot 元素,命名为 title,而且设置一个无内容时的默认值 default title。 使用的时候,咱们在元素中添加一个 slot 属性来与模版中的 slot 相匹配。

继承现有元素

至今,咱们都是彻底自定义组件内容,假如咱们想扩展示有系统元素,那就须要定义一个 内置自定义元素咱们来用一个屏蔽数字的 p 元素来讲明。

class PFilter extends HTMLParagraphElement {
    constructor() {
        super();
        const textContent = this.textContent;
        this.textContent = textContent.replace(/\d/g, '*');
    }
}
customElements.define(
    'p-filter',
    PFilter,
    {
        extends: 'p'
    }
)
复制代码

咱们这边再也不是继承 HTMLElement,而是继承须要扩展的 p节点 HTMLParagraphElement

<p is='p-filter'>个人手机号是:10086</p>
复制代码

不一样于独立自定义组件,咱们仍是须要用原有元素名去声明,而且在 is 属性中填写咱们的组件名。

生命周期

和大多数框架同样,Web Component 也含有许多控制组件生命周期的方法。

  1. connectedCallback:当 custom elemen t首次被插入 DOM 时,被调用。
  2. disconnectedCallback:当 custom element 从 DOM 中删除时,被调用。
  3. adoptedCallback:当 custom element 被移动到新的文档时,被调用。
  4. attributeChangedCallback: 当 custom element 增长、删除、修改自身属性时,被调用。

咱们只需在定义组件的类中声明对应的方法便可。attributeChangedCallback 相对与别的属性比较特别,他须要 搭配 observedAttributes 使用

class TextReverse extends HTMLElement {
    //...
    static get observedAttributes () {
        return ['text'];
    }
    attributeChangedCallback () {
        const text = this.getAttribute('text') || '';
        this.shadowRoot.getElementById('text').textContent = text.split('').reverse().join('');
    }
}
复制代码

咱们在 observedAttributes静态方法中添加须要监听的属性值。而后,在 text 改变的时候,触发 attributeChangedCallback方法来更新 text的值。

最后

Web Component 的功能十分强大,相较于 React,Vue等框架,他天生自带样式隔离,而且最主要的是拥有浏览器的原生支持。不过,想要达到工程开发标准 的话,他还有一段很长很长的路要走

相关文章
相关标签/搜索