Web Components 全揽
Web Components手艺能够把一组相干的HTML、JS代码和CSS作风打包成为一个自包含的组件,只需运用人人熟习的标签即可引入此组件。Web Components手艺包含:
- Custom Element
- Shadow DOM
- Template
- HTML Import
四个星散而又互相干的四个构造块。个中中心的即使是Custom Element、Shadow DOM,趁便会讲到而Template是一个支撑手艺。
HTML Import曾被Chrome到场然则随后和V0一同被烧毁。这里也不会议论它。
Custom Element 定制元素。
定制元素能够在原生元素外建立定制元素。定制元素是Web组件的一个基础组成块。能够在一个js文件内包含Custom Element须要的悉数要素,包含HTML模板、CSS Style和ES6类。并运用一个HTML文件,援用此js文件从而能够运用定制元素。
假定我们建立Spin Button,定制元素标签为:
<spin-button value=“100” step="10" min="50" max="150"></spin-button>
我们起首完成此定制元素,然则为了简朴起见,晚一点才看它的属性。此定制元素内部有一个加号按钮,一个减号按钮,一个span显现当前值。那末只须要把这个HTML模板构造、作风和代码组合在一个文件内:
var template = `
<button inc>+</button><span>1</span><button dec>-</button>
<style>
span{color:red;}
*{font-size:2rem;}
</style>
`
class SpinButton extends HTMLElement{
connectedCallback(){
this.innerHTML = template
var b1 = this.querySelector('[inc]')
var b2 = this.querySelector('[dec]')
var s = this.querySelector('span')
var i = 1
b1.onclick = function(){
s.innerHTML = i++
}
b2.onclick = function(){
s.innerHTML = i--
}
}
}
customElements.define('spin-button',SpinButton)
而且建立一个index.html文件加载此文件,即可运用新的定制元素spin-button了:
<script src="./spin.js"></script>
<spin-button></spin-button>
你能够看到实行在浏览器内的界面上的两个按钮和一个span。建立一个定制元素有几个要点:
- 新的JS定制类须要继续于类HTMLElement
- 回调connectedCallback供应一个生命周期事宜,当定制元素胜利挂接到DOM后,会挪用此回调,能够在此回调代码内到场自身的定制内容
- 代码中的this,指向了此定制元素自身,因而能够经由过程this.innerHTML设置本定制元素的内部DOM
如许,我们建立了一个奇特的定制元素,这个元素不在原生的浏览器标签内。
定制元素就是如许建立了,而且关于运用者来讲,只需经由过程熟习的元素标签,即可援用一组带有定制作风、操作和界面的组件了。
然则此时的定制元素有一个题目,就是它内部定义的作风,不单单议会影响内部的元素,也会泄漏到外部致使文档也被影响,从而激发我们不愿望的边际效应。比方在index.html内假如在文件尾部到场如许的文本:
<span>black</span>
你会发明black文本不是默许的色彩,而是赤色,如许赤色来自于定制元素内部的作风定义代码。假如愿望断绝组件内的作风定义,那末能够运用Shaddow DOM手艺。此主题会在下一部份内引见。
Shadow DOM
Web建站运用组件手艺有比较长的汗青了,这个手艺一直以来都有一个应战,就是怎样让一个页面能够运用第三方控件,然则不会被此组件运用的CSS作风所影响。解决方案是CSS能够部分化。想要组件内部的作风不会影响到外部,要领就是运用Shadow DOM。Shadow DOM建立了一个断绝区,在这个断绝区内的DOM是自力的,这意味着:
- 内部DOM Tree不会被外部文档接见到
- 也不会被外部的作风设置影响
- 内部的作风也不会影响到外部文档
我们拿前一个案例代码做试验,看看假如运用这个手艺特征。
运用Shadow DOM的症结,是起首建立一个Shadow Node,全部组件内部的HTML片断都插进去到此节点内,而不是直接运用组件的innerHTML。我们能够在组件对象的构造器内实行此代码:
class SpinButton extends HTMLElement{
constructor(){
super()
var shadow = this.attachShadow({mode:'open'})
var t = document.createElement('template')
t.innerHTML = template
shadow.appendChild(t.content.cloneNode(true))
}
}
实行后,你会发明span的作风不再影响组件以外的标签。看起来照样很简朴的,只需把你原本须要构造的HTML内部DOM插进去到shadow节点内即可。
定制元素的属性
元素的属性被称为Attribute,JS对象内的属性被称为Property。代码通例上每个Attribute都邑有JS对象的一个Property对应。为了轻易,我们愿望增加的Attribute能够和JS内的Property同步。就是说,假如有人经由过程HTML DOM API修正了Attribute,那末我愿望关于的JS属性会被同步修正;反之亦然,有人修正了Property,那末这个修正能够会同步修正到对应的Attribute。
我们以spin-button的value属性为例。定义一个一般的Property的要领是经由过程get/set症结字,比方定义value:
get value(){}
set value(newValue){}
随后就能够运用object.value
接见此属性值,或许经由过程object.value = newValue
为属性设置新值。能够在两个函数内经由过程代码设置和Attribute同步:
get value(){
return this.getAttribute('value') || 1
}
set value(v){
this.setAttribute('value',v)
}
如许代码内经由过程对属性value的接见,末了都邑致使对Attribute的接见。假如有代码对Attribute接见,怎样修正Attribute的同时同步更新Property呢。这就须要应用HTMLElement供应的生命周期要领了:
static get observedAttributes() {
return ['value'];
}
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case 'value':
break;
}
}
要领observedAttributes听过返回值声明须要视察的属性,如许就能够在指定属性清单发作更新时经由过程另一个生命周期要领attributeChangedCallback
,关照代码变化的状况。做相应的同步处置惩罚。整合后的代码以下:
var template = `
<button inc>+</button><span>1</span><button dec>-</button>
<style>
span{color:red;}
*{font-size:2rem;}
</style>
`
class SpinButton extends HTMLElement{
constructor(){
super()
var shadow = this.attachShadow({mode:'open'})
var t = document.createElement('template')
t.innerHTML = template
shadow.appendChild(t.content.cloneNode(true))
var b1 = shadow.querySelector('[inc]')
var b2 = shadow.querySelector('[dec]')
this.s = shadow.querySelector('span')
var i = 1
var that = this
b1.onclick = function(){
that.s.innerHTML = ++that.value
}
b2.onclick = function(){
that.s.innerHTML = -- that.value
}
}
static get observedAttributes() {
return ['value'];
}
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case 'value':
this.s.innerHTML = newValue
break;
}
}
get value(){
return this.getAttribute('value') || 1
}
set value(v){
this.setAttribute('value',v)
}
}
customElements.define('spin-button',SpinButton)
状况
Web Components的症结组成手艺包含Custom Element和Shadow DOM,最早在Chrome完成,第一个版本被称为V0然则其他浏览器没有跟进,因而逐渐被烧毁。本文议论的是V1版本。Firefox也已完成了V1版本。
能够在网站Whatcaniuse查询当前支撑状况。
ref
- Posts of wb
https://alligator.io/web-comp…
- Custom Elements v1: Reusable Web Components
https://developers.google.com…
*3. web-components-examples
https://github.com/mdn/web-co…
- Firefox 63 – Tricks and Treats!
https://hacks.mozilla.org/201…
- HTML Web Component using Plain JavaScript
https://www.codementor.io/ayu…
6. Doing something with Web Components
https://medium.com/@dalaidunc…