一 概述
自定义元素的名称必须包含中划线;必须有起始标签、结束标签,不能写成闭合标签。
二 项目结构
在HBuilder中创建普通项目。
三 代码
1 index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Web Component自定义元素</title>
</head>
<body>
<!-- Jimmy的名片 -->
<user-card id="first" image="./img/kristy.png" name="Jimmy" email="Jimmy@163.com"></user-card>
<!-- Aaja的名片 -->
<user-card id="first" image="./img/kristy.png" name="Aaja" email="Aaja@163.com"></user-card>
<script src="./js/user-card.js"></script>
</body>
</html>
2 user-card.js
// 创建HTMLTemplateElement模版元素
const template = document.createElement('template');
template.innerHTML = `
<!-- 左侧图片 -->
<img class="image" />
<!-- 右侧内容 -->
<div class="container">
<p class="name"></p>
<p class="email"></p>
<button class="button">Follow</button>
</div>
<!-- 样式表 -->
<link rel="stylesheet" type="text/css" href="./css/user-card.css"/>
`;
// 用户名片类
class UserCard extends HTMLElement {
// 被观察的属性值
static get observedAttributes() {
return ['image', 'name', 'email'];
}
// 影子根
shadowRoot;
$img;
$name;
$email;
constructor() {
super();
// user-card元素挂载影子DOM
this.shadowRoot = this.attachShadow({
mode: 'open'
});
// 因为模版元素被多个自定义元素实例共享,故需要深拷贝
const content = template.content.cloneNode(true);
this.shadowRoot.appendChild(content);
this.$img = this.shadowRoot.querySelector('img');
this.$name = this.shadowRoot.querySelector(".container>.name");
this.$email = this.shadowRoot.querySelector(".container>.email");
}
// 属性值变化回调
attributeChangedCallback(name, oldVal, newVal) {
console.log('user-card元素属性值变化', name, oldVal, newVal);
this.render();
}
// 插入文档后回调
connectedCallback() {
console.log('user-card元素已插入文档');
}
// 从文档删除后回调
disconnectedCallback() {
console.log('user-card元素已从文档删除');
}
// 自定义渲染方法
render() {
this.$img.setAttribute("src", this.getAttribute("image"));
this.$name.innerText = this.getAttribute("name");
this.$email.innerText = this.getAttribute("email");
}
}
// 注册自定义元素
window.customElements.define("user-card", UserCard);
3 样式
/* 挂载影子DOM后,:host伪类才有效。否则,应使用user-card元素选择器。 */
:host {
display: flex;
align-items: center;
margin-bottom: 10px;
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;
}
四 运行效果
?
五 参考文章
?阮一峰?Web Components 入门实例教程
|