当前位置:网站首页>[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
createElement
And set whether the behavior of the attribute value is a bit like React OfReact.createElement
Well ?
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 withVue
It'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.createElement
Of 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
边栏推荐
- Jiuxian's IPO was terminated: Sequoia and Dongfang Fuhai were shareholders who had planned to raise 1billion yuan
- 几行代码搞定RPC服务注册和发现
- What is generics- Introduction to generics
- Tech talk activity preview | building intelligent visual products based on Amazon kVs
- QWebEngineView崩溃及替代方案
- How to transfer business data with BorgWarner through EDI?
- Nexus Introduction and Xiaobai use idea Packaging and Upload to Nexus 3 private service detailed tutoriel
- traceroute命令讲解
- Use of openpose
- What is agile development process
猜你喜欢
Jiuxian's IPO was terminated: Sequoia and Dongfang Fuhai were shareholders who had planned to raise 1billion yuan
智能垃圾桶(五)——点亮OLED
社交元宇宙平台Soul冲刺港股:年营收12.8亿 腾讯是股东
What if the default browser cannot be set?
酒仙网IPO被终止:曾拟募资10亿 红杉与东方富海是股东
Blog theme "text" summer fresh Special Edition
电脑自带软件使图片底色变为透明(抠图白底)
七张图,学会做有价值的经营分析
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
如何与博格华纳BorgWarner通过EDI传输业务数据?
随机推荐
酒仙网IPO被终止:曾拟募资10亿 红杉与东方富海是股东
Qwebengineview crash and alternatives
相信自己,这次一把搞定JVM面试
社交元宇宙平台Soul冲刺港股:年营收12.8亿 腾讯是股东
深度之眼(二)——矩阵及其基本运算
Linux Installation PostgreSQL + Patroni cluster problem
Smart trash can (V) - light up OLED
Interpretation of key parameters in MOSFET device manual
博客主题 “Text“ 夏日清新特别版
剑指 Offer 22. 链表中倒数第k个节点
Method of C language self defining function
求简单微分方程
Nexus Introduction and Xiaobai use idea Packaging and Upload to Nexus 3 private service detailed tutoriel
綠竹生物沖刺港股:年期內虧損超5億 泰格醫藥與北京亦莊是股東
Dstat use [easy to understand]
绿竹生物冲刺港股:年期内亏损超5亿 泰格医药与北京亦庄是股东
上传代码到远程仓库报错error: remote origin already exists.
超卓航科上市:募资9亿市值超60亿 成襄阳首家科创板企业
IDEA2021.1 安装教程
Use the API port of the bridge of knowledge and action to provide resources for partners to access