prefácio
Como o autor está aprendendo sobre micro-frontends recentemente, web component
que também é um dos principais recursos, alguns frameworks de micro-frontend são usados, e eu estudei o conhecimento relevante em profundidade e o compartilhei.
O que são componentes da Web?
Web Component é na verdade uma combinação de uma série de tecnologias, incluindo principalmente 3 partes:
- Elementos personalizados. Estenda o elemento de rótulo personalizado para fora do rótulo HTML básico, que é o "componente" do framework que costumamos usar;
- Sombra DOM. É usado principalmente para isolar o conteúdo do Shadow DOM do documento externo DOM, que pode ser entendido como um subcontêiner no documento para colocar vários componentes;
- Modelos HTML. Use
<template>
para definir modelos de componentes,<slot>
use como slots (Vuer não deve ser estranho);
Um em um arquivo html web component
se parece com isto:
<trace-ele name="webComponent" version="0.0.1" desc="原生态自带隔离的组件">
<div slot="slot-ele">插槽内容</div>
</trace-ele>
Parece muito com o Vue, certo? Em seguida, vamos aprender as demonstrações uma a uma web component
.
bom
Devido Web Component
à afinidade nativa, não há necessidade de depender de outros pacotes index.html
e index.js
você pode experimentar o aprendizado um por um.
Escrevemos diretamente um modelo html e os componentes de caso do artigo são chamados coletivamente<trace-ele />
index.html:
<body>
<template id="trace">
<div class="container">
<img
class="image"
src="https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp"
alt=""
/>
<p class="title">学习Web Component</p>
<p class="desc">Web Component是微前端沙盒隔离原理的重要知识</p>
<p class="price">¥25.00</p>
</div>
</template>
<trace-ele />
<script src="./index.js" />
</body>
Aqui escrevemos um "modelo" - template
e declaramos <trace-ele />
os componentes abaixo.
E o princípio de perceber tudo isso está no index.js
.
class Trace extends HTMLElement {
constructor() {
super();
const templateEle = document.getElementById("trace");
const cloneEle = templateEle.content.cloneNode(true);
this.appendChild(cloneEle);
}
}
customElements.define("trace-ele", Trace);
Web Component
A essência de um componente é que uma classe herda dele HTMLElement
. Depois que customElements.define
o componente é declarado, o ponteiro na classe this
aponta para o próprio componente. Os resultados impressos são os seguintes:
Ao inicializar, você precisa fornecer ao componente um shell vazio e vincular template
o id do elemento para que o efeito do componente apareça.
Parece Vue
semelhante a ver aqui? Em seguida, vamos continuar a atualizar as funções dos componentes~
vamos estilizar
Com base na seção anterior, é muito simples adicionar um estilo ao componente, index.html
basta alterá-lo e template
adicionar style
:
<body>
<template id="trace">
<div class="container">
<img
class="image"
src="https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp"
alt=""
/>
<p class="title">学习Web Component</p>
<p class="desc">Web Component是微前端沙盒隔离原理的重要知识</p>
<p class="price">¥25.00</p>
</div>
<style>
.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;
font-size: 14px;
}
.price {
font-size: 14px;
}
</style>
</template>
<trace-ele />
<script src="./index.js" />
</body>
Os estilos entram em vigor:
Mas aqui se você der um estilo de rótulo geral, assim:
<body>
<p>组件外的P标签</p>
<template>
<p>组件中的P标签</p>
<style>
p {
color: red;
}
...
.container {
}
</style>
</template>
</body>
O efeito é o seguinte:
Pode-se ver que a parte externa do componente p标签
também é afetada e a cor muda para vermelho, mas no conceito do componente, espera-se que esse estilo aja apenas no próprio componente. Este também é o conceito de isolamento de estilo e, felizmente, Web Component
é fornecida uma solução de isolamento de estilo pronta para uso.
Para evitar conflitos <template>
entre o <style>
CSS interno e o CSS global, podemos pendurar o componente no Shadow Root e, em seguida, usar o Shadow Root para pendurá-lo no DOM do documento externo, para que o isolamento do CSS possa ser alcançado:
class Trace extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: "open" });
const templateEle = document.getElementById("trace");
const cloneEle = templateEle.content.cloneNode(true);
this.shadowRoot.appendChild(cloneEle);
}
}
customElements.define("trace-ele", Trace);
Observe no console:
E se houver vários componentes, a essência é que document
haja vários em Shadow Root
.
Todo o diagrama de arquitetura DOM é o seguinte:
Uma das vantagens do Shadow DOM é que ele pode isolar a estrutura, o estilo e o comportamento do DOM do Document DOM. É muito adequado para o encapsulamento de componentes, portanto, pode se tornar um dos componentes importantes do Web Component.
Adereços
Vue
Igual a e React
, Web Component
também fornece a forma de pai para filho.
index.html:
<trace-ele name="webComponent" version="0.0.1" desc="原生态自带隔离的组件">
Aqui 3 props são passados para o componente e impressos no componente this
da seguinte forma:
Com olhos atentos, encontrei a entrada para aceitar a passagem de parâmetros em componentes:
Faça uma atribuição dinâmica simples:
class Trace extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: "open" });
const templateEle = document.getElementById("trace");
const cloneEle = templateEle.content.cloneNode(true);
cloneEle.querySelector('.container > .title').textContent = this.getAttribute('name');
cloneEle.querySelector('.container > .price').textContent = this.getAttribute('version');
cloneEle.querySelector('.container > .desc').textContent = this.getAttribute('desc');
this.shadowRoot.appendChild(cloneEle);
}
}
customElements.define("trace-ele", Trace);
pronto~
slot
Outro benefício dos modelos HTML é que eles podem Vue
ser usados como arquivos <slot>
. Por exemplo, agora podemos <trace-ele>
adicionar um slot na parte inferior disso:
<body>
<template id="trace">
<div class="container">
<p>组件中的P标签</p>
<img
class="image"
src="https://pic1.zhimg.com/50/v2-a6d65e05ec8db74369f3a7c0073a227a_200x0.webp"
alt=""
/>
<p class="title">学习Web Component</p>
<p class="desc">Web Component是微前端沙盒隔离原理的重要知识</p>
<p class="price">¥25.00</p>
<slot name="slot-ele"></slot>
</div>
<style>
...
</style>
</template>
<trace-ele name="webComponent" version="0.0.1" desc="原生态自带隔离的组件">
<div slot="slot-ele">插槽内容</div>
</trace-ele>
</body>
Dessa forma, podemos implementar conteúdo de slot personalizado.
ligação de evento
Web Component
Você também pode vincular eventos a elementos ou slots em componentes.
class Trace extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: "open" });
const templateEle = document.getElementById("trace");
const cloneEle = templateEle.content.cloneNode(true);
cloneEle
.querySelector(".container > .title")
.addEventListener("click", this.onClick);
this.shadowRoot.appendChild(cloneEle);
}
onClick = () => {
alert("Click Me!");
};
}
customElements.define("trace-ele", Trace);
Resumir
O exposto acima compartilhou principalmente com você alguns métodos de uso do Web Component. Em geral, Web Component é uma combinação de uma série de APIs:
- Elemento personalizado : registrar e usar componentes
- Shadow DOM : Isolar CSS
- Modelo HTML e slot : estrutura DOM flexível
Parece ser a implementação de infraestrutura da estrutura principal atual, e a estrutura também é baseada nos recursos nativos para implementar um conjunto completo de soluções, como rastreamento responsivo do Vue e ligação de dados de sintaxe de modelo, todos os quais queremos ver.