Web Components
浏览器原生组件,不用加载外部模块,代码量小。它允许用户创建可重用的定制元素,并在web应用中使用它们。
使用方法
一、自定义元素
自定义HTML标签称为自定义元素,自定义元素的名称必须包含连词线(如:user-card),用于区别原生HTML元素。
自定义元素的方法:
1. 自定义UserCard类
class UserCard extends HTMLElement {
constructor() {
super();
}
}
2. 使用浏览器原生的customElements.define()
方法,告诉浏览器user-card
元素与该类相连
window.customElements.define('user-card',UserCard)
3. 在页面中直接插入以下标签即可使用
<user-card></user-card>
二、自定义元素的内容
给自定义元素添加内容包括两种方式
1. 通过JS添加
// 1. 定义继承自HTMLElement的UserCard类
class UserCard extends HTMLElement {
// 2. 编写构造函数
constructor() {
// 3. 继承父类方法,必写
super();
// 4. 创建自定义的页面元素
// 4.1 创建class为container的div
var container = document.createElement("div");
container.classList.add("container");
// 4.2 创建class为name,innerHTML为“姓名:XXX”的p标签
var name = document.createElement("p");
name.classList.add("name");
name.innerText = "姓名:XXX";
// 4.3 创建class为email,内容为“邮箱:XXX”的p标签
var email = document.createElement("p");
email.classList.add("email");
email.innerText = "邮箱:XXX";
// 4.4 创建class为button,文字为“详细信息”的button按钮
var button = document.createElement("button");
button.classList.add("button");
button.innerText = "详细信息";
// 将name,email,button添加为container的子元素
container.append(name, email, button);
// this.append()的this表示<user-card></user-card>。
// 将container 的内容填入<user-card></user-card>
this.append(container);
}
}
// 声明"user-card"代表刚刚定义的UserCard
window.customElements.define("user-card", UserCard);
完成这一步以后,自定义元素内部的 DOM 结构就已经生成了。
2. 通过 template 标签添加
<template>
标签可以用来在HTML中定义DOM,它由Web Components API 提供。用于避免使用JS写DOM结构(很麻烦)。
完整代码如下:
<body>
<user-card></user-card>
<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>
<script>
// 改写一下自定义元素的类,为自定义元素加载<template>。
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>
三、添加样式
为自定义元素指定样式:把样式写在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>
四、自定义元素参数
自定义元素允许调用时传入不同数据形成个性化显示。
实现方式:通过在<user-card>
添加属性和值,在JS中通过this.getAttribute()
获取个性化数值,实现个性化展示。
<user-card
image="https://semantic-ui.com/images/avatar2/large/kristy.png"
name="User Name"
email="yourmail@some-email.com"
></user-card>
<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>
<script>
class UserCard extends HTMLElement {
constructor() {
super();
var templateElem = document.getElementById('userCardTemplate');
var content = templateElem.content.cloneNode(true);
content.querySelector('img').setAttribute('src', this.getAttribute('image'));
content.querySelector('.container>.name').innerText = this.getAttribute('name');
content.querySelector('.container>.email').innerText = this.getAttribute('email');
this.appendChild(content);
}
}
window.customElements.define('user-card', UserCard);
</script>
五、shadow DOM
用于将<user-card>
的内部代码隐藏,让用户看不到。且内部代码无法影响外部。
开启方法:this.attachShadow()
class UserCard extends HTMLElement {
constructor() {
super();
// { mode:'closed' }表示Shadow DOM 是封闭的,不允许外部访问。
var shadow = this.attachShadow( { mode: 'closed' } );
var templateElem = document.getElementById('userCardTemplate');
var content = templateElem.content.cloneNode(true);
content.querySelector('img').setAttribute('src', this.getAttribute('image'));
content.querySelector('.container>.name').innerText = this.getAttribute('name');
content.querySelector('.container>.email').innerText = this.getAttribute('email');
shadow.appendChild(content);
}
}
window.customElements.define('user-card', UserCard);
六、组件的扩展
添加监听事件
this.$button = shadow.querySelector('button');
this.$button.addEventListener('click', () => {
// do something
});
组件的封装
将js脚本与<template>
封装成js文件,形成独立的组件文件。网页只要加载这个脚本就可以使用<user-card>
组件。
参考链接
阮一峰—Web Components 入门实例教程https://www.ruanyifeng.com/blog/2019/08/web_components.html