用Vanilla JavaScript创建网络组件
网络应用程序开发是一个相当拥挤的技术领域。有不同类型的框架、库和工具。在开发Web应用时,主要的目标是用封装的组件提供高质量的用户界面(UI)。
因此,当你使用React、Vue、Angular等框架或其他前端框架时,你会将用户界面中的所有东西分解成组件。然而,我们甚至不需要使用框架或库就可以做类似的事情,这就是普通的JavaScript(Vanilla JavaScript)。
本文将讨论什么是Web组件,以及为什么它们会有帮助。最后,它将带你了解如何从头开始创建一个网络组件。
前提条件
网络组件是一个奇妙的、互动的指南。因此,需要对HTML、CSS和JavaScript有良好的理解。
什么是网络组件
网络组件是为网页和应用程序增加功能和特性的一组规范。例如,它们允许HTML元素的可重用性和封装性。
网络组件使你能够建立可以在不同的网络平台、应用程序或页面上重复使用的功能。
网络组件由三种领先的技术组成,用于创建可以在你喜欢的时候重复使用的自定义元素。它们包括。
- 自定义元素:这些API允许你定义和创建自定义元素以提供所需的用户界面。
- 影子DOM:启用封装的API。特定的元素从你的主DOM中分离出来,从而防止诸如文档碰撞等问题。
- HTML模板:允许你声明不在页面上显示的标记模板片段的元素。这些元素被用作模板,可以在多个地方重复使用。
包括chrome、firefox和edge在内的网络浏览器提供对网络组件的支持。这意味着技术,即(自定义元素、阴影DOM和HTML模板)被完全支持。
这张来自webcomponents.org的图片显示了当前web组件的浏览器支持情况。

为什么使用网络组件
事实证明,代码的可重用性是很有用的,在网络组件启动之前,要实现一个可重用的用户界面,并在不同的框架和项目中发挥作用是不容易的。
网络组件允许网络开发者使用内置的网络API来构建可重用的UI。这意味着我们可以为一个项目创建一个Web组件,并把它带到另一个项目中,而不需要额外的编码。
用vanilla JavaScript创建一个Web组件
本教程用Vanilla JavaScript或在没有任何框架或库的帮助下创建一个Web组件。
我们将创建一个员工卡的Web组件。它将包含一个用户图片、姓名、ID、工作职位、电话和电子邮件。下面是我们将使用的用户图像。

我们将首先创建一个index.html 和employee-card.js 文件。然后复制并粘贴这些代码。
<!DOCTYPE html>
<html lang="en">
<head>
<title>Web Components</title>
<style>
h2{
color: purple;
}
</style>
</head>
<body>
<h2>Employee Card Example</h2>
<employee-card name="Leah Crystal" avatar=image.png></employee-card>
<div slot="id"><b>ID:</b> 238</div>
<div slot="job title"><b>Job Title:</b> Database Administrator</div>
<div slot="email"><b>Email:</b> lcrystal34@gmail.com</div>
<div slot="phone"><b>Phone:</b> 292-856-410</div>
<!-- scripts -->
<script src="employee-card.js"></script>
</body>
</html>
为了创建一个雇员卡的网络组件,创建一个.js 文件。让我们把它命名为employee-card.js 复制并粘贴这段代码。
const template = document.createElement('template');
template.innerHTML = `
<style>
<style>
.employee-card {
font-family: sans-serif;
background: #f4f6f7;
width: 250px;
display: grid;
grid-template-columns: 1fr;
margin-bottom: 10px;
}
</style>
<div class="employee-card">
<img/>
<div>
<h3></h3>
<div class="details">
<p><slot name="id"/></p>
<p><slot name="job title"/></p>
<p><slot name="email"/></p>
<p><slot name="phone"/></p>
</div>
</div>
</div>`;
class EmployeeCard extends HTMLElement{
constructor(){
super();
this.attachShadow({ mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
this.shadowRoot.querySelector('h3').innerText = this.getAttribute('name');
this.shadowRoot.querySelector('img').src = this.getAttribute('avatar');
}
connectedCallback(){
this.h3 = this.getAttribute("name")
this.render();
}
render(){
this.h3;
}
}
window.customElements.define('employee-card', EmployeeCard);
上面的代码显示了如何创建一个员工卡网络组件,所以让我们一步一步地理解每一部分。
创建模板
const template = document.createElement('template');
第一步是创建一个HTML内容模板元素<template> 。<template> 元素存放运行页面后不会立即呈现的HTML。
用内容加载模板
template.innerHTML = `
<style>
<style>
.employee-card {
font-family: sans-serif;
background: #f4f6f7;
width: 250px;
display: grid;
grid-template-columns: 1fr;
margin-bottom: 10px;
}
</style>
<div class="employee-card">
<img/>
<div>
<h3></h3>
<div class="details">
<p><slot name="id"/></p>
<p><slot name="job title"/></p>
<p><slot name="email"/></p>
<p><slot name="phone"/></p>
</div>
</div>
</div>
`;
模板元素被存储在一个template 变量中,并与inner HTML 属性相连。innerHTML 属性设置了该元素上的HTML内容。因此,我们可以添加我们想在屏幕上显示的HTML,如<div> ,<p> ,以及更多的HTML元素。
创建HTML元素
class EmployeeCard extends HTMLElement{}
我们创建一个扩展了HTMLElement类的EmployeeCard 。HTMLElement代表所有的HTML元素。
封装HTML元素
constructor(){
super();
this.attachShadow({ mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
this.shadowRoot.querySelector('h3').innerText = this.getAttribute('name');
this.shadowRoot.querySelector('img').src = this.getAttribute('avatar');
}
我们有一个空的类。接下来,我们创建一个构造函数并调用基类super() 方法来继承一个类的特征。
一个影子DOM被创建,即this.attachShadow({ mode: 'open'}) ,并成为我们网络组件的封装部分。它使我们的组件的行为独立于Html的其他部分。
你可以让你的影子DOM模式关闭或打开。这意味着你是否可以在你的组件中通过JavaScript访问影子DOM。
Web 组件使我们能够使用影子 DOM,这是浏览器内置的一个功能。因此,如果子元素被添加到一个组件的影子DOM中,它们会被包裹在一个影子根里面。
this.shadowRoot.querySelector('h3').innerText = this.getAttribute('name');
this.shadowRoot.querySelector('img').src = this.getAttribute('avatar')
然后,Web组件的API会得到属性名称和头像,以显示在页面上。
生命周期方法
connectedCallback(){
this.h3 = this.getAttribute("name")
this.render();
}
render(){
this.h3;
}
有四个回调方法定义在自定义元素里面。它们使代码能够在元素发生事件时运行。
让我们看看其中的一些回调方法。
connectedCallback:当组件被插入到HTML文档的DOM时被调用。disconnectedCallback:当该元素从文档的DOM中移除时被调用。adoptedCallback:当组件被移动到另一个HTML文档时被调用。attributeChangedCallback:是当组件的属性被改变时。
创建自定义元素
window.customElements.define('employee-card', EmployeeCard);
我们的网络组件已经创建完毕,但还剩下一个步骤:创建自定义元素。在创建自定义元素时,我们使用JavaScript类EmployeeCard 。在这里,该类继承了HTML Element 的属性。
最后,为了测试我们是否创建了一个员工卡网络组件,用浏览器打开index.html 文件。其输出结果如下所示。

结语
通过本教程,你已经学会了如何用vanilla JavaScript构建一个简单的Web组件。
希望你已经了解了网络组件,为什么它们是有用的,以及如何建立一个。此外,创建一个网络组件可以使用react.js和vue.js等框架来实现。因此,我鼓励你继续探索和尝试。