从入门到放弃:Web Components

谁在搜索Web Components?

搜索Web Components的通常是不使用Web Components的,就像你和我,但是由于闲着没事和热爱学习,又或者应付一下前端面试,不得不了解下。

不使用Web Components是有很多客观原因的,例如你和Web Components之间大概有n个前端框架,这些框架是你面试工作必备的,不单你要有基于其它们的大型应用的实战,而且还要有理解其源码原理的能力。

所以Web Components很自然成为你的短板之一。

为什么Web Components

个人觉得这些年前端一直围绕着一个问题:组件化,比如前端三国演义(React,Vue,Angular)的发展及其火热程度足以说明,但是有一个问题一直没解决,那就是组件复用问题,说白就是怎么防止重复造轮子问题,尽管我不认为这是问题,但是W3C认为这是问题,所以我们不得不来学习Web Components

W3C的解决方法就是,通过制定规范和标准,让所有浏览器提供一系列平台API来支持自定义HTML标签,这样你基于这些API所编写的组件就可以运行在所有支持的浏览器中,从而达到组件复用。

Web Components的内容

如果你被W3C或者网上其它言论洗脑,你会相信Web Components就是未来,什么三国演义都会俱往矣,所以你需要知道怎么样去编写Web Components

首先Web Components基于四个规范:自定义元素,影子DOM,ES模块,HTML模版,我劝你还是别点进去,规范就像懒婆娘的裹脚,又臭又长,一个简单的hello world或todo才是浅尝辄止的我们所需要的。

hello-world.js

const template = document.createElement('template');

template.innerHTML = `
  
  

Hello: World

`; class HelloWorld extends HTMLElement { constructor() { super(); this._shadowRoot = this.attachShadow({ mode: 'open' }); this._shadowRoot.appendChild(template.content.cloneNode(true)); this.$headline = this._shadowRoot.querySelector('h2'); this.$span = this._shadowRoot.querySelector('span'); } connectedCallback() { if(!this.hasAttribute('color')) { this.setAttribute('color', 'orange'); } if(!this.hasAttribute('text')) { this.setAttribute('text', ''); } this._render(); } static get observedAttributes() { return ['color', 'text']; } attributeChangedCallback(name, oldVal, newVal) { switch(name) { case 'color': this._color = newVal; break; case 'text': this._text = newVal; break; }; this._render(); } _render() { this.$headline.style.color = this._color; this.$span.innerHTML = this._text; } } window.customElements.define('hello-world', HelloWorld);

hello-world.html



  
    Hello World Web Components
  
  
    
    
  

可以看出写一个组件还是算简单的,其实现在你的脑海里大致有个Web Components的雏形了,接下来我们来分析一下每一行的代码,及其所对应的规范和标准。

1. 自定义元素定义:
class HelloWorld extends HTMLElement {...}

只要继承HTMLElement类,你便可以编写自定义标签/元素,里面的构造函数和生命周期函数暂时都不要管。

2. HTML模版
const template = document.createElement('template');
template.innerHTML = ...

HTML