Web Components 原生组件 Trends

在现在前端组件化开发大行其道的今天,各种Framework让人眼花缭乱,同一个公司,不同团队,可能使用的是不同的框架。那么在统一视觉,交互,功能上,不同的框架可以都需要用不同的框架开发一遍,但是在功能和交互有所改变的时候,又需要全部同步开发一次。这种对人力和物力都是一种消耗,而且维护性也不是很好,那么有没有一种组件可以兼容所有的框架,并且开发和维护方便呢?那么Web Components可能就是你需要的答案。

Web Components是原生提供的一种技术,他允许创建可重用的定制元素。

概念

Web Components 是原生提供的一种技术,可以自定义UI控件。Web Components由四项技术组成。

  • Custom elements(自定义元素)
  • Shadow DOM(影子DOM)
  • HTML templates(HTML模板)
  • HTML Imports(HTML导入)
  1. Custom elements 一组javascript API,允许你定义custom element及其行为。
customElements.define('jason-custom',
  class extends HTMLElement {
    constructor() {
      super()

      let jasonTestElem = document.createElement('div');
      jasonTestElem.textContent = this.getAttribute('text');

      let shadowRoot = this.attachShadow({mode: 'open'})
        .appendChild(jasonTestElem)
  }
})
复制代码

使用CustomElementRegistry对象来生成custom elements,该对象允许你注册一个custom element

customElements.define()接受三个参数:

  • DOMString 创建元素的名称(custom element名称中必须包含短横线);
  • 类对象 定于类的行为;
  • 一个包含extends属性的对象,可选参数,指定创建的元素继承自哪个内置元素。

custom elment共有两种:

  • Autonomous custom elements 是一种独立元素,他不继承任何一种HTML元素,你可以在页面中直接使用它,比如<jason-elm></jason-elm>, 或者document.createElement('jason-elm')
  • Customized built-in elements 继承基本的HTML元素,创建时,你必须要继承自某个基本的HTML元素,使用的时候需在基本元素中通过is属性指定名称。比如<p is='jason-elm'></p>, 或者document.createElement('p', { is: 'jason-elm'})

例子:

Autonomous custom elements

class JasonCustom extends HTMLElement {
    constructor() {
        super()
        
        let divElem = document.createElement('div')
        divElem.textContent = 'This is a test Autonomous custom element'
        
        let shadowRoot = this.attachShadow({mode: 'open'})
        shadowRoot.appendChild(divElem)
    }
}
customElements.define('jason-custom', JasonCustom)
复制代码

那么我们就可以在页面中使用他了<jason-custom />

Customized built-in elements

class JasonCustom extends HTMLUListElement {
    construtor() {
        super()
        //
    }
}

customElements.define('jason-custom', JasonCustom, { extends: 'ul' })
复制代码

在页面中使用这种自定义的元素使用 <ul is='jason-custom' />

自定义组件的生命周期回调函数

  • connectedCallback: 当custom element 首次被插入文档DOM时,被调用。
  • disconnectedCallback: 当 custom element从文档DOM中删除时,被调用。
  • adoptedCallback: 当 custom element被移动到新的文档时,被调用。
  • attributesChangedCallback: 当 custom element增加、删除、修改自身属性时,被调用。

使用声明周期回调函数的例子可以在线看life-cycle-callbacks

Shadow DOM

Web components 一个重要特性就是封装,他可以将HTML, CSS,和行为隐藏起来,并从页面上的其他代码分开起来,这样不用的功能就不会混在一起。那么就是要介绍的Shadow DOM, shadow DOM可以将隐藏的独立的元素添加到一个元素上。

Shadow DOM允许将隐藏的DOM添加到常规的DOM树中

Shadow DOM

Shadow DOM 有几个概念

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

你可以像操作基本的DOM元素一样操作Shadow DOM元素,你也可以给Shadow DOM添加<style>而且只影响Shadow DOM里的元素。Shadow DOM的标准意味着你可以为自己的元素维护一组Shadow DOM。

用法

可以使用Element.attachShadow()来为任意一个元素添加Shoadow DOM,attachShadow里接受一个对象作为参数,参数有个属性mode,有两个可选值open close

let shadowOpen = Elementp.attachShadow({'mode': open})
let shadowClose = Elementp.attachShadow({'mode': close})
复制代码

open 可以通过javascript来获取shandow DOM 例如

let shadowDom = Elementp.shadowRoot
复制代码

close的话,就是不可以在外部获取到shadow Dom 了,访问shadowRoot就会返回null

更具体的文章请查看 Open vs. Closed Shadow DOM(有可能需要科学上网)

templates slot

对的,没有错,现在原生提供了模板的功能!!这种模板不会被浏览器渲染但是可以使用javascript调用!

官方例子

<template id="my-paragraph">
  <p>My paragraph</p>
</template>
复制代码

使用的时候怎么用呢

let template = document.getElementById('my-paragraph');
let templateContent = template.content;
document.body.appendChild(templateContent);
复制代码

你可以用slot 增加template的灵活度,slot的作用是用来提供一个占位的

slot使用 name 属性作为id, 你能在tempalte 中定义任意的 html 片断作为占位符,在模板对象被使用在html 脚本中时。 例如:

// tamplate
<p><slot name="my-text">My default text</slot></p>

// 使用时
<my-paragraph>
  <span slot="my-text">Let's have some different text!</span>
</my-paragraph>

//生成的html
<p><span>Let's have some different text!</span></p>
复制代码

当然上面这些代码都算是农耕时代的代码,那么可以让我们用工业2.0的效率来开发web Components 组件的框架有Google的polymer,ionic 自己的stencil

虽然这个标准好久就出现了,但是其实一直没有很多的开发者介入。可能源于这玩意的兼容性。

可以看到除了chrome高版本和safari是支持最完全的。但是这玩意多好玩的啊,可以拿来做实验性的产品来玩玩多好!

Stay Hungry. Stay Foolish

猜你喜欢

转载自juejin.im/post/5b4f520df265da0f8b2faccc