当前位置:网站首页>[web technology] 1233 seconds understand web component
[web technology] 1233 seconds understand web component
2022-07-02 17:22:00 【pingan8787】
What is it?
Web Components In fact, a combination of a series of technologies , It mainly includes 3 part :
Custom elements . stay HTML Extend custom label elements beyond the basic label
Shadow DOM. Mainly used to Shadow DOM Content and outer layer of document DOM Isolation
HTML Templates . Use
<template>To define component templates , Use<slot>Use as a slot
It is precisely because it is a series of API The combination of , So in use , We need to focus on these at the same time API The compatibility of :



After using the above technology reasonably , Can Will function 、 Custom logic is encapsulated in the tag , Improve development efficiency by reusing these custom components . It sounds like Vue.js and React The one you made , actually , In the use of Web Components When , It's also very similar .
Get started
Next, we implement a <book-card> Web Component Let's learn how to use it .

Custom elements
First , Create a index.html, Call directly inside <book-card> Components .
<body>
<book-card></book-card>
<script src="./BookCard.js"></script>
</body> Because browsers don't know <book-card> therefore , We need to be in BookCard.js Register it in , And in index.html Introduce and execute BookCard.js.
class BookCard extends HTMLElement {
constructor() {
super();
const container = document.createElement('div')
container.className = 'container'
const image = document.createElement('img')
image.className = 'image'
image.src = "https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp"
const title = document.createElement('p')
title.className = 'title'
title.textContent = ' The sacrifice of Chernobyl '
const desc = document.createElement('p')
desc.className = 'desc'
desc.textContent = 'S·A· Alexeyevich '
const price = document.createElement('p')
price.className = 'price'
price.textContent = `¥25.00`
container.append(image, title, desc, price)
this.appendChild(container)
}
}
customElements.define('book-card', BookCard)The above has realized the most basic DOM It's structured :

The above has been executing
createElementAnd set whether the behavior of the attribute value is a bit like React OfReact.createElementWell ?
HTML Templates
This generates... Line by line DOM The structure is not only tired of writing , It is also difficult for readers to understand at once . To solve this problem , We can use HTML Templates . Directly in HTML There's a <template> Templates :
<body>
<template id="book-card-template">
<div class="container">
<img class="image" src="https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp" alt="">
<p class="title"> The sacrifice of Chernobyl </p>
<p class="desc">S·A· Alexeyevich </p>
<p class="price">¥25.00</p>
</div>
</template>
<book-card></book-card>
<script src="BookCard.js"></script>
</body>Then call this template directly in the registration component :
class BookCard extends HTMLElement {
constructor() {
super();
const templateElem = document.getElementById('book-card-template')
const clonedElem = templateElem.content.cloneNode(true)
this.appendChild(clonedElem)
}
}
customElements.define('book-card', BookCard)In this way
<template>Is the writing style a little like what we are familiar withVueIt's framed ?
Writing style
done DOM after , Then we can write the style , Directly in <template> Add a new one to it <style> Elements , Then start writing CSS:
<body>
<template id="book-card-template">
<style>
p { margin: 0 }
.container { display: inline-flex; flex-direction: column; border-radius: 6px; border: 1px solid silver; padding: 16px; margin-right: 16px }
.image { border-radius: 6px; }
.title { font-weight: 500; font-size: 16px; line-height: 22px; color: #222; margin-top: 14px; margin-bottom: 9px; }
.desc { margin-bottom: 12px; line-height: 1; color: #8590a6; font-size: 14px; }
.price { color: #8590a6; font-size: 14px; }
</style>
<div class="container">
<img class="image" src="https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp" alt="">
<p class="title"> The sacrifice of Chernobyl </p>
<p class="desc">S·A· Alexeyevich </p>
<p class="price">¥25.00</p>
</div>
</template>
<book-card></book-card>
<script src="BookCard.js"></script>
</body>I believe everyone will write like this CSS, So in order to reduce the length, we put CSS It's folded , The final effect is as follows :

Shadow DOM
In order not to let <template> Inside <style> CSS And the overall situation CSS There are conflicts , We can hang the components to Shadow Root On , Reuse Shadow Root Hanging on the outer layer document DOM On , In this way... Can be achieved CSS Isolation of :
class BookCard extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' })
const templateElem = document.getElementById('book-card-template')
const clonedElem = templateElem.content.cloneNode(true)
this.shadowRoot.appendChild(clonedElem)
}
}
customElements.define('book-card', BookCard) Open console , You can see <template> Of DOM All hung up on Shadow Root Yes :

Whole DOM The architecture is roughly like this :

Shadow DOM One of the great advantages of is the ability to DOM structure 、 style 、 Behavior and Document DOM To separate from each other , It is very suitable for packaging components , So it can be Web Component An important part of .
Shadow DOM It often appears in our daily development , such as <video> In the element controls Control DOM The structure is also hung on Shadow Root Under the :

Props
and Vue and React The components are the same , We can also do that Web Component Pass attributes on :
<body>
<template id="book-card-template">
<style>
...
</style>
<div class="container">
<img class="image" src="" alt="">
<p class="title"></p>
<p class="desc"></p>
<p class="price"></p>
</div>
</template>
<book-card
data-image="https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp"
data-title=" The sacrifice of Chernobyl "
data-desc="S·A· Alexeyevich "
data-price="25.00"
></book-card>
<script src="BookCard.js"></script>
</body>Then update these properties to DOM On :
const prefix = 'data-'
class BookCard extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' })
const templateElem = document.getElementById('book-card-template')
const clonedElem = templateElem.content.cloneNode(true)
clonedElem.querySelector('.container > .image').src = this.getAttribute(`${prefix}image`)
clonedElem.querySelector('.container > .title').textContent = this.getAttribute(`${prefix}title`)
clonedElem.querySelector('.container > .desc').textContent = this.getAttribute(`${prefix}desc`)
clonedElem.querySelector('.container > .price').textContent = `¥${this.getAttribute(`${prefix}price`)}`
this.shadowRoot.appendChild(clonedElem)
}
}
customElements.define('book-card', BookCard) Generally speaking , For custom properties , We are used to using data-xxx Named after the .
If you can think further , You can get these directly
attributes, Then use it to do Proxy agent 、 Responsive assignment and other operations . Um. , Yes Vue It's too delicious !
const prefix = 'data-'
const attrList = Array.from(this.attributes);
const props = attrList.filter(attr => attr.name.startsWith(prefix))
// monitor props
watch(props)Slot
HTML Another advantage of templates is that they can be like Vue The use of <slot>. such as , Now we can be here <book-card> Add a... At the bottom action slot :
<template id="book-card-template">
<style>
...
</style>
<div class="container">
<img class="image" src="" alt="">
<p class="title"></p>
<p class="desc"></p>
<p class="price"></p>
<div class="action">
<slot name="action-btn"></slot>
</div>
</div>
</template> When others want to use <book-card> When the component , You can use them through slots and inject their customized content :
<book-card
data-image="https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp"
data-title=" The sacrifice of Chernobyl "
data-desc="S·A· Alexeyevich "
data-price="25.00"
>
<button slot="action-btn" class="btn primary"> Buy </button>
</book-card>
<book-card
data-image="https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp"
data-title=" The sacrifice of Chernobyl "
data-desc="S·A· Alexeyevich "
data-price="25.00"
>
<button slot="action-btn" class="btn danger"> Delete </button>
</book-card>
Interaction
We can still be like React Bind events to elements like that , For example, here for this action <slot> Add click event :
class BookCard extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' })
const templateElem = document.getElementById('book-card-template')
const clonedElem = templateElem.content.cloneNode(true)
...
clonedElem.querySelector('.container > .action').addEventListener('click', this.onAction)
this.shadowRoot.appendChild(clonedElem)
}
onAction = () => {
alert('Hello World')
}
}
Be careful : there onAction Is the arrow function , Because you need to bind this, Point it to this BookCard Components .
UI library
Maybe some students have begun to think : Since this thing can be used to encapsulate components , There is a corresponding Web Component UI The library? ? The answer is yes .
At present, there are some famous products produced by Microsoft FAST[2]:

Yes Google Produced Lit[3]:

And Tencent of our factory OMI[4]:

summary
The above mainly shares with you Web Component Some usage methods . in general ,Web Component Is a series of API The combination of :
Custom Element: Register and use components
Shadow DOM: Isolation CSS
HTML template and slot: agile DOM structure
About Web Component The content of , It's almost finished , I don't know how you feel after reading . It gives me the feeling that it provides the function of native component encapsulation , But there are a lot of things not done , For example, what we want to see :
image Vue That kind of responsive tracking of data
image Vue That kind of template syntax 、 Data binding
image React Like that DOM Diff
image React Like that
React.createElementOf JSX How to write it...
These are what we hope “ Frame features ” Web Component Are not provided . This is because Web Component All the contents are made by API form , And these API As a specification, keep the function single 、 The principle of orthogonality , Instead of acting like Vue, React Such componentization “ frame ”. I know that, too 《Web Component And the class React、Angular、Vue Who will become the future of component technology ?》[5] The answer said :
The responsibility of the framework is to provide a complete set of solutions , And the platform API The design requirement of is never to provide a complete set of solutions ( That is to ensure zero coupling 、 orthogonal ), This is the fundamental contradiction that cannot be reconciled .
Web Component The main benefit is native support 、 No external dependence . One index.html + main.js You can complete the component registration and use .
at present , It's still developing , It can also be used in production environments , image single-spa Layout Engine as well as MicroApp It's an example , Another scenario is that you can TextArea, Video Such functional components are used in Web Component To encapsulate .
Reference material
[1]
Project code : https://github.com/haixiangyan/bookcard-web-component
[2]FAST: https://www.fast.design/
[3]Lit: https://lit.dev/
[4]OMI: https://tencent.github.io/omi/
[5]《Web Component And the class React、Angular、Vue Who will become the future of component technology ?》: https://www.zhihu.com/question/58731753/answer/158331367

1. JavaScript Revisit the series (22 Complete )
2. ECMAScript Revisit the series (10 Complete )
3. JavaScript Design patterns Revisit the series (9 Complete )
4. Regular / frame / Algorithm etc. Revisit the series (16 Complete )
5. Webpack4 introduction ( On )|| Webpack4 introduction ( Next )
6. MobX introduction ( On ) || MobX introduction ( Next )
7. 120+ Summary of original series

reply “ Add group ” Communicate and learn with the big guys ~
Click on “ Read the original ” see 130+ Original articles
边栏推荐
- Dgraph: large scale dynamic graph dataset
- Win10系统使用pip安装juypter notebook过程记录(安装在系统盘以外的盘)
- Vscode setting delete line shortcut [easy to understand]
- Weili holdings listed on the Hong Kong Stock Exchange: with a market value of HK $500million, it contributed an IPO to Hubei
- 博客主题 “Text“ 夏日清新特别版
- Briefly introduce the use of base64encoder
- Usage of sprintf() function in C language
- 如何与博格华纳BorgWarner通过EDI传输业务数据?
- 二、mock平台的扩展
- 宝宝巴士创业板IPO被终止:曾拟募资18亿 唐光宇控制47%股权
猜你喜欢

GeoServer:发布PostGIS数据源

对接保时捷及3PL EDI案例

What if the default browser cannot be set?

宝宝巴士创业板IPO被终止:曾拟募资18亿 唐光宇控制47%股权

QStyle实现自绘界面项目实战(二)

A case study of college entrance examination prediction based on multivariate time series

Cell: Tsinghua Chenggong group revealed an odor of skin flora. Volatiles promote flavivirus to infect the host and attract mosquitoes

Fuyuan medicine is listed on the Shanghai Stock Exchange: the market value is 10.5 billion, and Hu Baifan is worth more than 4billion

871. Minimum refueling times

Configure MySQL under Linux to authorize a user to access remotely, which is not restricted by IP
随机推荐
The computer comes with software to make the background color of the picture transparent (matting white background)
Use the API port of the bridge of knowledge and action to provide resources for partners to access
What if the default browser cannot be set?
默认浏览器设置不了怎么办?
QStyle实现自绘界面项目实战(二)
A case study of college entrance examination prediction based on multivariate time series
ssb门限_SSB调制「建议收藏」
酒仙网IPO被终止:曾拟募资10亿 红杉与东方富海是股东
綠竹生物沖刺港股:年期內虧損超5億 泰格醫藥與北京亦莊是股東
一文看懂:数据指标体系的4大类型
如何与博格华纳BorgWarner通过EDI传输业务数据?
dstat使用[通俗易懂]
Usage of sprintf() function in C language
体验居家办公完成项目有感 | 社区征文
How to transfer business data with BorgWarner through EDI?
Sword finger offer 21 Adjust the array order so that odd numbers precede even numbers
伟立控股港交所上市:市值5亿港元 为湖北贡献一个IPO
上传代码到远程仓库报错error: remote origin already exists.
chmod命令原理及用法详解[通俗易懂]
Baobab's gem IPO was terminated: Tang Guangyu once planned to raise 1.8 billion to control 47% of the equity