在现在前端组件化开发大行其道的今天,各种Framework让人眼花缭乱,同一个公司,不同团队,可能使用的是不同的框架。那么在统一视觉,交互,功能上,不同的框架可以都需要用不同的框架开发一遍,但是在功能和交互有所改变的时候,又需要全部同步开发一次。这种对人力和物力都是一种消耗,而且维护性也不是很好,那么有没有一种组件可以兼容所有的框架,并且开发和维护方便呢?那么Web Components可能就是你需要的答案。
Web Components是原生提供的一种技术,他允许创建可重用的定制元素。
概念
Web Components 是原生提供的一种技术,可以自定义UI控件。Web Components由四项技术组成。
- Custom elements(自定义元素)
- Shadow DOM(影子DOM)
- HTML templates(HTML模板)
- HTML Imports(HTML导入)
- 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 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是支持最完全的。但是这玩意多好玩的啊,可以拿来做实验性的产品来玩玩多好!