当前位置:网站首页>[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
边栏推荐
- Tech talk activity preview | building intelligent visual products based on Amazon kVs
- ThreadLocal
- 七张图,学会做有价值的经营分析
- A case study of college entrance examination prediction based on multivariate time series
- One year is worth ten years
- IP address translation address segment
- TCP拥塞控制详解 | 2. 背景
- 13、Darknet YOLO3
- class和getClass()的区别
- Un an à dix ans
猜你喜欢

对接保时捷及3PL EDI案例

Goodbye, shucang. Alibaba's data Lake construction strategy is really awesome!

剑指 Offer 22. 链表中倒数第k个节点

Soul, a social meta universe platform, rushed to Hong Kong stocks: Tencent is a shareholder with an annual revenue of 1.28 billion

移动应用性能工具探索之路

What if the default browser cannot be set?

Use the API port of the bridge of knowledge and action to provide resources for partners to access

剑指 Offer 26. 树的子结构

七张图,学会做有价值的经营分析

Sword finger offer 21 Adjust the array order so that odd numbers precede even numbers
随机推荐
Nexus簡介及小白使用IDEA打包上傳到Nexus3私服詳細教程
Chapter 3 of hands on deep learning - (1) linear regression is realized from scratch_ Learning thinking and exercise answers
ThreadLocal
Cell: Tsinghua Chenggong group revealed an odor of skin flora. Volatiles promote flavivirus to infect the host and attract mosquitoes
Un an à dix ans
Domestic relatively good OJ platform [easy to understand]
Chmod command principle and usage details [easy to understand]
TCP拥塞控制详解 | 2. 背景
什么是敏捷开发流程
关于我
PCL知识点——体素化网格方法对点云进行下采样
Exploration of mobile application performance tools
The poor family once again gave birth to a noble son: Jiangxi poor county got the provincial number one, what did you do right?
QWebEngineView崩溃及替代方案
Dstat use [easy to understand]
OpenPose的使用
一年頂十年
QStyle实现自绘界面项目实战(二)
ROS知识点——ros::NodeHandle n 和 nh(“~“)的区别
Configure ARP table entry restrictions and port security based on the interface (restrict users' private access to fool switches or illegal host access)