
组件是后端的演进方向,现在流行的 React 和 Vue 都是组件框架。
谷歌公司由于掌握了 Chrome 浏览器,一直在实现浏览器的原生模块,即 Web Components API。相比第三方框架,原生模块简单直接,符合直觉,不用加载任何内部组件,代码量小。目前,它还在不断发展,但尚未可用于制造环境。
Web Components API 内容太多,本文不是全面的教程,只是一个简单演示,让你们看一下怎么用它开发组件。

下图是一个用户卡片。

本文演示怎样把这个卡片,写成 Web Components 组件,这里是最终的完整代码。
网页只要插入以下的代码,就会显示用户卡片。
<user-card></user-card>
这种自定义的 HTML 标签webcomponents可以删除吗,称为自定义元素(custom element)。根据完善,自定义元素的名称应该包括连词线,用与差别原生的 HTML 元素。所以,<user-card>不能写成<usercard>。
自定义元素应该使用 JavaScript 定义一个类,所有<user-card>都会是这个类的例子。
class UserCard extends HTMLElement {
constructor() {
super();
}
}
上面代码中,UserCard就是自定义元素的类。注意,这个类的父类是HTMLElement,因此继承了 HTML 元素的特性。
接着,使用浏览器原生的customElements.define()方法,告诉浏览器<user-card>元素与这个类关联。
window.customElements.define('user-card', UserCard);
自定义元素<user-card>目前还是空的,下面在类里边给出这个元素的内容。
class UserCard extends HTMLElement {
constructor() {
super();
var image = document.createElement('img');
image.src = 'https://semantic-ui.com/images/avatar2/large/kristy.png';
image.classList.add('image');
var container = document.createElement('div');
container.classList.add('container');
var name = document.createElement('p');
name.classList.add('name');
name.innerText = 'User Name';
var email = document.createElement('p');
email.classList.add('email');
email.innerText = 'yourmail@some-email.com';
var button = document.createElement('button');
button.classList.add('button');
button.innerText = 'Follow';
container.append(name, email, button);
this.append(image, container);
}
}
上面代码最后一行,this.append()的this表示自定义元素实例。
完成这一步以后,自定义元素内部的 DOM 结构就早已生成了。
使用 JavaScript 写上一节的 DOM 结构很麻烦,Web Components API 提供了<template>标签,可以在它上面使用 HTML 定义 DOM。
<template id="userCardTemplate">
<img src="https://semantic-ui.com/images/avatar2/large/kristy.png" class="image">
<div class="container">
<p class="name">User Name</p>
<p class="email">yourmail@some-email.com</p>
<button class="button">Follow</button>
</div>
</template>
然后,改写一下自定义元素的类,为自定义元素加载<template>。
class UserCard extends HTMLElement {
constructor() {
super();
var templateElem = document.getElementById('userCardTemplate');
var content = templateElem.content.cloneNode(true);
this.appendChild(content);
}
}
上面代码中,获取<template>节点之后,克隆了它的所有子元素,这是因为可能有多个自定义元素的例子,这个模版还要留给其它例子使用,所以不能直接移动它的子元素。
到这一步为止,完整的代码如下。
<body>
<user-card></user-card>
<template>...</template>
<script>
class UserCard extends HTMLElement {
constructor() {
super();
var templateElem = document.getElementById('userCardTemplate');
var content = templateElem.content.cloneNode(true);
this.appendChild(content);
}
}
window.customElements.define('user-card', UserCard);
</script>
</body>
自定义元素还没有样式,可以给它指定全局风格,比如上面那样。
user-card {
/* ... */
}
但是,组件的风格必须与代码封装在一起,只对自定义元素生效,不妨碍内部的全局风格。所以,可以把风格写在<template>里面。
<template id="userCardTemplate">
<style>
:host {
display: flex;
align-items: center;
width: 450px;
height: 180px;
background-color: #d4d4d4;
border: 1px solid #d5d5d5;
box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.1);
border-radius: 3px;
overflow: hidden;
padding: 10px;
box-sizing: border-box;
font-family: 'Poppins', sans-serif;
}
.image {
flex: 0 0 auto;
width: 160px;
height: 160px;
vertical-align: middle;
border-radius: 5px;
}
.container {
box-sizing: border-box;
padding: 20px;
height: 160px;
}
.container > .name {
font-size: 20px;
font-weight: 600;
line-height: 1;
margin: 0;
margin-bottom: 5px;
}
.container > .email {
font-size: 12px;
opacity: 0.75;
line-height: 1;
margin: 0;
margin-bottom: 15px;
}
.container > .button {
padding: 10px 25px;
font-size: 12px;
border-radius: 5px;
text-transform: uppercase;
}
</style>
<img src="https://semantic-ui.com/images/avatar2/large/kristy.png" class="image">
<div class="container">
<p class="name">User Name</p>
<p class="email">yourmail@some-email.com</p>
<button class="button">Follow</button>
</div>
</template>

上面代码中,<template>样式上面的:host伪类,指代自定义元素本来。
<user-card>内容以后是在<template>里面设置的,为了便于使用,把它改成参数。
<user-card
image="https://semantic-ui.com/images/avatar2/large/kristy.png"
name="User Name"
email="yourmail@some-email.com"
></user-card>
<template>代码也相应改造。
<template id="userCardTemplate">
<style>...</style>
<img class="image">
<div class="container">
<p class="name"></p>
<p class="email"></p>
<button class="button">Follow John</button>
</div>
</template>
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/sanxing/article-120725-1.html
是吃着中国的粮食
只要进入12海里
晚上你直接去他家就可以了