Web Component入门
Web Component入门
- 原文出自: https://levelup.gitconnected.com/web-components-in-a-nutshell-1e114aa971b9
- 原标题: Web Components in a Nutshell
- 原副标题: 原生浏览器Web Component基础和如何创建
- 翻译文章同步发表在团队的语雀上
说明: 以下使用Web组件来表示Web Component
正文:
在web开发中,代码复用已成为一个聚焦重点。作为一名开发者,我们可能会遇到这样的场景,在多个地方使用一个代码片段来表示自定义的UI。如果我们不是很小心的写出,这可能会让整个代码结构变得不可管理。Web组件提供了一个原生的API来构建可复用的UI块。
什么是Web组件?
Web组件是一系列用来帮助我们创建可复用、具备封装的自定义HTML UI元素的浏览器底层的API。Web组件被认为更加好,是因为他们可以用任意的库或者框架创建,而且你可以立马使用原生JavaScript开始创建你自己的Web组件。
使用Web组件的一大优势在于他们已经在除了微软Edge外其他浏览器中可用,但是我们并不需要担心,因为已经有Polyfills可以解决这个问题。
Web组件由3个主要的技术组成,他们是主要支柱并作为API来构建Web组件。
- 自定义元素(Custom Elements)
- 模板(Templates)
- 影子DOM(Shadow DOM)
让我们来进一步了解这些技术。
1. 自定义元素(Custom Elements)
这些是JavaScript API的集合,可以帮助你创建自己的HTML元素,并且控制你的DOM和行为。我们可以构建他们的层级和指示他们对行为变化做出的响应。例如,你可以创建一个元素像这样<my-element></my-element>
。
2. 模板(Templates)
模板是用户定义的模板在页面加载时并不渲染。之后可以通过创建一个组件实例来多次复用。
3. 影子DOM(Shadow DOM)
影子DOM是JavaScript API组合用以连接封装的DOM。这将会从主文档对象模型中独立渲染,并且他们的行为特性将会保持私有,因此代码片段就不会和代码结构中的其他部分冲突。使用影子DOM后CSS和JavaScript就会像<iframe>
一样分离。
生命周期回调
生命周期回调是定义在自定义元素类定义中的函数。他们有自己唯一的定义目的。他们用于操作我们自定义元素的行为。
connectedCallback
: 这个特殊的函数会在我们的自定义元素初始连接到DOM时进行调用。adoptedCallback
: 这个函数会在我们的自定义函数移动到一个新的文档时调用。attributeChangedCallback
: 如果在我们的自定义元素中有属性变化,例如属性的变更、增加或者删掉,这个特殊的函数会被调用。disconnectedCallback
: 这个特殊的函数当我们的自定义元素从DOM中断开时调用。
现在让我们来看看如何使用原生JavaScript来创建一个Web组件。通过做完这个教程,你可以了解Web组件。
实战
我们要构建什么?
我们要构建一个显示一张当前热门图片的Web组件。我们会使用Giphy API来获取gif,你的代码结构在实现完成后会是如下:
--index.html
--card.js
--services.js
构建教程
首先,我们要创建一个类来包含我们想创建的Web组件的行为。创建一个card.js
的文件,并创建一个如下的类。
class CardComponent extends HTMLElement {
constructor (){
super();
//Your implementaion goes here
}
}
在类的构造函数中,你需要通过Element.attachShadow()
方法将影子DOM的影子根(shadow root)添加到文档的当前HTML元素中。接着使用<template>
标签在index.html
文件中创建HTML模板。这个模板如下:
<template id="card-view">
<h1>Web Component</h1>
<p id="card-title">Example</p>
<img id="gif-view"/>
</template>
在添加模板到我们的index.html
文件中后,我们可以使用DOM方法来克隆上面的模板并添加到我们的影子DOM。这需要在构造函数中完成。
class CardComponent extends HTMLElement {
constructor (){
super();
const shadow = this.attachShadow({mode: 'open'});
// Clone the template so that it can be attched to the shadowroot
const template = document.getElementById('card-view');
const templateInstance = template.content.cloneNode(true);
shadow.appendChild(templateInstance);
}
}
就像我之前提到的,我们应该再写一个函数来从Giphy API中获取gif。从API中我们将获取到当前热门的图片,以及这个图片上传者提供的标题。在我们开始写这个函数前,先创建一个单独的文件services.js
用以放置URL和API key。创建文件并放置以下代码和你申请的API key。
const API_KEY = '*YOUR_API_KEY*';
const url = `http://api.giphy.com/v1/gifs/trending?api_key=` + API_KEY + `&limit=1`;
export {API_KEY, url}; // export the url so that i can be used extrnally.
创建services.js
文件后,添加以下的代码到你的card.js
文件顶部,这样你就可以使用URL来获取gif图片了。
import { url } from './services.js';
你可以从这个链接获取你自己的API key: https://developers.giphy.com/
跳回到card.js
文件,并添加以下函数:
render(shadowElem, data){
const shadowRoot = shadowElem.shadowRoot;
shadowRoot.getElementById('card-title').innerHTML = data.name;
shadowRoot.getElementById('gif-view').src = data.url;
}
async fetchFromGiphy (){
const res = await fetch(url);
const json = await res.json();
const gifUrl = json['data']['0'].images['fixed_height_small'].url;
const gifName = json['data']['0'].title;
const gifObject = {
name: gifName,
url: gifUrl
}
return gifObject;
}
让我来解释一下这些函数。
fetchFromGiphy()
: 这个函数使用async/await获取热门的gif和这个gif的标题,并作为对象进行返回。
render()
: 这个函数用于注入值到影子DOM的元素中。
接着,让这些函数在生命周期回调中被调用。实际上,我们需要当我们的自定义元素连接到DOM时调用这两个函数。我们有connectedCallback()
函数来实现。
async connectedCallback() {
this.gifObj = await this.fetchFromGiphy();
this.render(this, this.gifObj);
}
最后,使用customElements.define()
函数来定义我们的自定义元素。当定义一个自定义元素时,有一些基本原则需要记在心里。define()
函数的第一个参数应该是代码自定义元素名称的字符串。他们不能是一个单独的单词,而是由-
字符在中间。第二个参数我们的定义元素行为的类对象。
customElements.define(‘card-component’, CardComponent);
现在你已经定义了你的组件,添加card.js
文件到你的index.html
文件中。你可以在HTML文档的任意地方使用<card-component>
元素。最后的index.html
如下:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Web Component</title>
</head>
<body>
<template id="card-view">
<h1>Web Component</h1>
<p id="card-title">Example</p>
<img id="gif-view"/>
</template>
<card-component></card-component>
<script src="./card.js" type="module"></script>
</body>
</html>
为了运行,你需要一个服务器。从命令行中全局安装static-server
:
npm install -g static-server
从你的Web组件项目目录下运行static-server
命令:
static-server
好了,恭喜!你现在已经拥有你自己的组件。
结论
这篇文章总结了Web组件的基础。这是Web组件的理论和实现。Web组件在帮助代码复用上很有用。你可以从这个项目中检出所有代码。