组成
Web Components
由三部分组成
Custom element
(自定义元素)Shadow DOM(影子 DOM
: 使组件保持独立,解决冲突的HTML template
(HTML 模板):作为组件的基础,能够被复用HTMLImports弃用
示例
编写一个user-info
组件
第五步 使用自定义标签
<user-info></user-info>
第一步 编写template组件模板
<template id="userInfo">
<style>
.container {
width: 100px;
height: 100px;
background-color: antiquewhite;
}
</style>
<div class="container">
<p>username</p>
<p>email</p>
<p>password</p>
</div>
</template>
<script>
第二步 编写自定义组件
class UserInfo extends HTMLElement {
static get Tag_Name() {
return "user-info"
}
constructor() {
super()
第三步 使用影子dom,将标记结构、样式和行为隐藏起来,并与页面上的其他代码相隔离
const template = document.querySelector("#userInfo")
const shadow = this.attachShadow({ mode: "closed" })
const content = template.content.cloneNode(true)
shadow.appendChild(content)
}
}
第四步 注册组件
customElements.define(UserInfo.Tag_Name, UserInfo)
</script>
思考:为什么不直接使用template.content
而要使用cloneNode
呢?
因为这个模板可能会被更多的customElement
使用,自定义组件只能修改副本,不能更改本体。
template与slot
slot
就是一个占位标签,你可以选择替换它,如果不替换他将显示默认内容
<M-div>
<ul slot="default">
随便一个带slot属性的标签去替换slot标签
<li>Let's have some different text!</li>
<li>In a list!</li>
</ul>
</M-div>
<template id='Mdiv'>
<slot name='default'>slot标签里面的是默认内容</slot>
</template>
模板分离
前面我将组件放在了同一个文件中,但实际情况组件应该是一个独立的文件。
在以前我们可以使用<link rel="import" href="component.html">
,但是现在HTML import
已经被弃用了,
我们可以使用es module
,但是es module
属于js模块方案,它并不支持template
这种html
的模板语法,我们只能使用纯js了。
- 编写
js
的Web Components
组件
let template = `
<template id='userInfo'>
<style>
.user-info{
width:100px;
height:100px;
background-color:blue;
}
</style>
<div class='user-info'>
<p>username</p>
<p>password</p>
</div>
</template>
`
const parser = new DOMParser()
const doc = parser.parseFromString(template, "text/html")
const temp = doc.getElementById("userInfo")
class userInfo extends HTMLElement {
constructor() {
super()
const shadow = this.attachShadow({ mode: "closed" })
const content = temp.content.cloneNode(true)
shadow.append(content)
}
}
customElements.define("user-info", userInfo)
export default userInfo
注意:我这里解析字符串用的是DOMPaser
,这个api返回的是一个document
对象并不是一个dom
,这个需要注意
2. 现在就可以使用这个组件了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
这里使用的是es module
<script type="module" src="./component.js"></script>
</head>
<body>
直接使用这个组件
<user-info></user-info>
<script></script>
</body>
</html>