Os elementos personalizados permitem que os desenvolvedores Web definam novas tags HTML, estendam as existentes e criem componentes da Web reutilizáveis.
Com os Elementos personalizados, os desenvolvedores Web podem criar novas tags HTML, melhorar as tags HTML existentes ou ampliar os componentes que outros desenvolvedores têm criados. A API é a base do Web e componentes de solução. Ele traz um baseada em padrões de criar componentes reutilizáveis usando apenas JavaScript/HTML/CSS básico. O resultado é menos código, código modular e mais reutilização em nossos apps.
Introdução
O navegador nos oferece uma excelente ferramenta para estruturar aplicativos da web. Está chamada HTML. Talvez você já tenha ouvido falar dele. É declarativa, portátil suportado e fácil de trabalhar. Ótimo como o HTML seja, seu vocabulário e e a extensibilidade são limitadas. A vida do HTML padrão sempre não teve uma maneira de associar automaticamente o comportamento do JS à sua marcação... até agora.
Os elementos personalizados são a resposta para a modernização do HTML, completando o que falta peças e agrupamento de estrutura com comportamento. Se o HTML não fornecer o solução para um problema, podemos criar um elemento personalizado que faça isso. Personalizado de recursos ensinam novos truques ao navegador, preservando os benefícios do HTML.
Definição de um novo elemento
Para definir um novo elemento HTML, precisamos do poder do JavaScript!
O objeto global customElements
é usado para definir um elemento personalizado e ensinar
o navegador sobre uma nova tag. Chamar customElements.define()
com o nome da tag.
que você quer criar e um class
JavaScript que estenda a base HTMLElement
.
Exemplo: definir um painel de gaveta para dispositivos móveis, <app-drawer>
:
class AppDrawer extends HTMLElement {...}
window.customElements.define('app-drawer', AppDrawer);
// Or use an anonymous class if you don't want a named constructor in current scope.
window.customElements.define('app-drawer', class extends HTMLElement {...});
Exemplo de uso:
<app-drawer></app-drawer>
É importante lembrar que usar um elemento personalizado não é diferente
usando um <div>
ou qualquer outro elemento. As instâncias podem ser declaradas na página,
criados dinamicamente em JavaScript, listeners de eventos podem ser anexados etc. O Keep
para mais exemplos.
Definir a API JavaScript de um elemento
A funcionalidade de um elemento personalizado é definida usando um ES2015
class
que estende HTMLElement
. Estender HTMLElement
garante que o elemento personalizado
herda toda a API DOM e significa qualquer propriedade/método adicionado ao
se tornam parte da interface DOM do elemento. Basicamente, use a classe para
criar uma API JavaScript pública para sua tag.
Exemplo: definir a interface DOM de <app-drawer>
:
class AppDrawer extends HTMLElement {
// A getter/setter for an open property.
get open() {
return this.hasAttribute('open');
}
set open(val) {
// Reflect the value of the open property as an HTML attribute.
if (val) {
this.setAttribute('open', '');
} else {
this.removeAttribute('open');
}
this.toggleDrawer();
}
// A getter/setter for a disabled property.
get disabled() {
return this.hasAttribute('disabled');
}
set disabled(val) {
// Reflect the value of the disabled property as an HTML attribute.
if (val) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
}
// Can define constructor arguments if you wish.
constructor() {
// If you define a constructor, always call super() first!
// This is specific to CE and required by the spec.
super();
// Setup a click listener on <app-drawer> itself.
this.addEventListener('click', e => {
// Don't toggle the drawer if it's disabled.
if (this.disabled) {
return;
}
this.toggleDrawer();
});
}
toggleDrawer() {
// ...
}
}
customElements.define('app-drawer', AppDrawer);
Neste exemplo, estamos criando uma gaveta que tem uma propriedade open
, disabled
.
e um método toggleDrawer()
. Ele também reflete as propriedades como HTML
atributos.
Um recurso interessante de elementos personalizados é que this
dentro de uma definição de classe
refere-se ao próprio elemento DOM, ou seja, a instância da classe. Em nossa
Por exemplo, this
refere-se a <app-drawer>
. É assim (nerg) que o elemento pode
anexar um listener click
a si mesmo. E você não está limitado a listeners de eventos.
Toda a API DOM está disponível dentro do código do elemento. Use this
para acessar
propriedades do elemento, inspecionar seus filhos (this.children
), consultar nós
(this.querySelectorAll('.items')
) etc.
Regras para a criação de elementos personalizados
- O nome de um elemento personalizado precisa conter um traço (-). Então,
<x-tags>
,<my-element>
e<my-awesome-app>
são nomes válidos, enquanto<tabs>
e<foo_bar>
não. Esse requisito é para que o analisador HTML possa distinguir elementos personalizados de elementos regulares. Ele também garante o encaminhamento quando novas tags são adicionadas ao HTML. - Você não pode registrar a mesma tag mais de uma vez. A tentativa de fazer isso
gerar uma
DOMException
. Depois de informar o navegador sobre uma nova tag, reimplantá-lo. Não é possível reverter. - Os elementos personalizados não podem fechar automaticamente porque o HTML permite apenas alguns
elementos
fecham automaticamente. Sempre escreva uma tag de fechamento
(
<app-drawer></app-drawer>
).
Reações do elemento personalizado
Um elemento personalizado pode definir hooks de ciclo de vida especiais para executar o código durante em momentos interessantes da sua existência. Eles são chamados de elementos personalizados reações.
Nome | Chamado quando |
---|---|
constructor |
Uma instância do elemento é
criados ou atualizados. Útil para a inicialização
estado, configuração de listeners de eventos ou
Como criar um shadow DOM.
Consulte a
spec
para saber o que é possível fazer no constructor .
|
connectedCallback |
Chamado sempre que o é inserido no DOM. Útil para executar códigos de configuração, como a busca de recursos ou renderização. Em geral, você deve tentar atrasar o trabalho até este momento. |
disconnectedCallback |
Chamado sempre que o elemento é removido do DOM. Útil para e executar códigos de limpeza. |
attributeChangedCallback(attrName, oldVal, newVal) |
Chamado quando um atributo observado foi
adicionadas, removidas, atualizadas ou substituídas. Também chamado para valores iniciais
quando um elemento é criado pelo analisador ou
atualizado. Observação: somente
atributos listados na propriedade observedAttributes
para receber esse callback.
|
adoptedCallback |
O
elemento personalizado foi movido para um novo document (por exemplo,
alguém chamado document.adoptNode(el) ).
|
Os callbacks de reação são síncronos. Se alguém ligar para el.setAttribute()
no seu elemento, o navegador chamará attributeChangedCallback()
imediatamente.
Da mesma forma, você receberá um disconnectedCallback()
logo após o elemento ser
removido do DOM (por exemplo, o usuário chama el.remove()
).
Exemplo:adicionar reações de elemento personalizado a <app-drawer>
:
class AppDrawer extends HTMLElement {
constructor() {
super(); // always call super() first in the constructor.
// ...
}
connectedCallback() {
// ...
}
disconnectedCallback() {
// ...
}
attributeChangedCallback(attrName, oldVal, newVal) {
// ...
}
}
Defina as reações se/quando fizer sentido. Se o elemento for complexo o suficiente
e abrir uma conexão com o IndexedDB em connectedCallback()
, faça o que for necessário
trabalho de limpeza em disconnectedCallback()
. Mas tenha cuidado. Você não pode confiar nos seus
sendo removido do DOM em todas as circunstâncias. Por exemplo:
disconnectedCallback()
nunca será chamado se o usuário fechar a guia.
Propriedades e atributos
Refletir propriedades para atributos
É comum que as propriedades HTML reflitam seu valor de volta para o DOM como uma
atributo HTML. Por exemplo, quando os valores de hidden
ou id
são alterados
JavaScript:
div.id = 'my-id';
div.hidden = true;
os valores são aplicados ao DOM ativo como atributos:
<div id="my-id" hidden>
Isso é chamado de "refletir as propriedades para atributos". Quase todas as propriedades do HTML fazem isso. Por quê? Os atributos também são úteis para configurar um elemento de maneira declarativa e determinadas APIs, como acessibilidade e CSS os seletores dependem de atributos para funcionar.
Refletir uma propriedade é útil sempre que você quiser manter o DOM do elemento. em sincronia com o estado do JavaScript. Um motivo pelo qual você pode querer refletem uma propriedade, então o estilo definido pelo usuário é aplicado quando o estado do JS muda.
Lembre-se da nossa <app-drawer>
. Um consumidor desse componente pode querer esmaecê-lo
e/ou impedir a interação do usuário quando ela estiver desativada:
app-drawer[disabled] {
opacity: 0.5;
pointer-events: none;
}
Quando a propriedade disabled
é alterada no JS, queremos que esse atributo seja
adicionado ao DOM para que o seletor do usuário corresponda. O elemento pode fornecer
do comportamento refletindo o valor para um atributo com o mesmo nome:
get disabled() {
return this.hasAttribute('disabled');
}
set disabled(val) {
// Reflect the value of `disabled` as an attribute.
if (val) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
this.toggleDrawer();
}
Observar mudanças em atributos
Os atributos HTML são uma maneira conveniente para os usuários declararem o estado inicial:
<app-drawer open disabled></app-drawer>
Os elementos podem reagir a mudanças de atributos definindo uma
attributeChangedCallback
: O navegador chamará esse método para cada alteração
aos atributos listados na matriz observedAttributes
.
class AppDrawer extends HTMLElement {
// ...
static get observedAttributes() {
return ['disabled', 'open'];
}
get disabled() {
return this.hasAttribute('disabled');
}
set disabled(val) {
if (val) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
}
// Only called for the disabled and open attributes due to observedAttributes
attributeChangedCallback(name, oldValue, newValue) {
// When the drawer is disabled, update keyboard/screen reader behavior.
if (this.disabled) {
this.setAttribute('tabindex', '-1');
this.setAttribute('aria-disabled', 'true');
} else {
this.setAttribute('tabindex', '0');
this.setAttribute('aria-disabled', 'false');
}
// TODO: also react to the open attribute changing.
}
}
No exemplo, estamos definindo atributos adicionais na <app-drawer>
quando um
O atributo disabled
foi alterado. Embora não façamos isso aqui, é possível
também use o attributeChangedCallback
para manter uma propriedade JS sincronizada com o
Atributo.
Upgrades de elementos
HTML aprimorado progressivamente
Já aprendemos que elementos personalizados são definidos chamando
customElements.define()
: Mas isso não significa que você precisa definir + registrar uma
elemento personalizado de uma só vez.
Os elementos personalizados podem ser usados antes do registro da definição.
O aprimoramento progressivo é um recurso dos elementos personalizados. Em outras palavras, você pode
declarar vários elementos <app-drawer>
na página e nunca invocar
customElements.define('app-drawer', ...)
até muito mais tarde. Isso ocorre porque o
navegador trata possíveis elementos personalizados de forma diferente graças a uma palavra-chave desconhecida
tags. O processo de chamar define()
e aprimorar um
com uma definição de classe é chamado de "upgrade de elementos".
Para saber quando um nome de tag é definido, use
window.customElements.whenDefined()
: Ela retorna uma promessa que é resolvida quando
é definido.
customElements.whenDefined('app-drawer').then(() => {
console.log('app-drawer defined');
});
Exemplo: atrasar o trabalho até que um conjunto de elementos filhos seja atualizado
<share-buttons>
<social-button type="twitter"><a href="...">Twitter</a></social-button>
<social-button type="fb"><a href="...">Facebook</a></social-button>
<social-button type="plus"><a href="...">G+</a></social-button>
</share-buttons>
// Fetch all the children of <share-buttons> that are not defined yet.
let undefinedButtons = buttons.querySelectorAll(':not(:defined)');
let promises = [...undefinedButtons].map((socialButton) => {
return customElements.whenDefined(socialButton.localName);
});
// Wait for all the social-buttons to be upgraded.
Promise.all(promises).then(() => {
// All social-button children are ready.
});
Conteúdo definido pelo elemento
Elementos personalizados podem gerenciar seu próprio conteúdo usando as APIs do DOM código do elemento. As reações são úteis para isso.
Exemplo: crie um elemento com um HTML padrão:
customElements.define('x-foo-with-markup', class extends HTMLElement {
connectedCallback() {
this.innerHTML = "<b>I'm an x-foo-with-markup!</b>";
}
// ...
});
Declarar essa tag gera:
<x-foo-with-markup>
<b>I'm an x-foo-with-markup!</b>
</x-foo-with-markup>
// TODO: DevSite - Exemplo de código removido porque usava manipuladores de eventos in-line
Como criar um elemento que usa o Shadow DOM
O Shadow DOM permite que um elemento tenha, renderize e estilize um bloco de um DOM separado do restante da página. Você pode até esconder aplicativo inteiro com uma única tag:
<!-- chat-app's implementation details are hidden away in Shadow DOM. -->
<chat-app></chat-app>
Para usar o Shadow DOM em um elemento personalizado, chame this.attachShadow
dentro da
constructor
:
let tmpl = document.createElement('template');
tmpl.innerHTML = `
<style>:host { ... }</style> <!-- look ma, scoped styles -->
<b>I'm in shadow dom!</b>
<slot></slot>
`;
customElements.define('x-foo-shadowdom', class extends HTMLElement {
constructor() {
super(); // always call super() first in the constructor.
// Attach a shadow root to the element.
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(tmpl.content.cloneNode(true));
}
// ...
});
Exemplo de uso:
<x-foo-shadowdom>
<p><b>User's</b> custom text</p>
</x-foo-shadowdom>
<!-- renders as -->
<x-foo-shadowdom>
#shadow-root
<b>I'm in shadow dom!</b>
<slot></slot> <!-- slotted content appears here -->
</x-foo-shadowdom>
Texto personalizado do usuário
// TODO: DevSite - Exemplo de código removido porque usava manipuladores de eventos in-line
Como criar elementos usando uma <template>
Para quem não conhece, o <template>
elemento
permite declarar fragmentos do DOM que são analisados, ficam inertes no carregamento da página e
que podem ser ativados no momento da execução. É outro primitivo de API na Web.
família de componentes. Os modelos são um marcador de posição ideal para declarar os
estrutural de um elemento personalizado.
Exemplo:registrar um elemento com conteúdo do Shadow DOM criado usando um
<template>
:
<template id="x-foo-from-template">
<style>
p { color: green; }
</style>
<p>I'm in Shadow DOM. My markup was stamped from a <template>.</p>
</template>
<script>
let tmpl = document.querySelector('#x-foo-from-template');
// If your code is inside of an HTML Import you'll need to change the above line to:
// let tmpl = document.currentScript.ownerDocument.querySelector('#x-foo-from-template');
customElements.define('x-foo-from-template', class extends HTMLElement {
constructor() {
super(); // always call super() first in the constructor.
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(tmpl.content.cloneNode(true));
}
// ...
});
</script>
Essas poucas linhas de código fazem um grande sucesso. Vamos entender os principais pontos em:
- Estamos definindo um novo elemento em HTML:
<x-foo-from-template>
- O Shadow DOM do elemento é criado usando uma
<template>
- O DOM do elemento é local em relação ao elemento graças ao Shadow DOM
- O CSS interno do elemento tem o escopo definido para o elemento graças ao Shadow DOM
Estou no Shadow DOM. Minha marcação foi estampada de um <template>.
// TODO: DevSite - Exemplo de código removido porque usava manipuladores de eventos in-line
Definir o estilo de um elemento personalizado
Mesmo que o elemento defina o próprio estilo usando o Shadow DOM, os usuários podem estilizar seu elemento personalizado na página. Eles são chamados de "estilos definidos pelo usuário".
<!-- user-defined styling -->
<style>
app-drawer {
display: flex;
}
panel-item {
transition: opacity 400ms ease-in-out;
opacity: 0.3;
flex: 1;
text-align: center;
border-radius: 50%;
}
panel-item:hover {
opacity: 1.0;
background: rgb(255, 0, 255);
color: white;
}
app-panel > panel-item {
padding: 5px;
list-style: none;
margin: 0 7px;
}
</style>
<app-drawer>
<panel-item>Do</panel-item>
<panel-item>Re</panel-item>
<panel-item>Mi</panel-item>
</app-drawer>
Talvez você esteja se perguntando como funciona a especificidade de CSS se o elemento tem estilos definidos no Shadow DOM. Em termos de especificidade, os estilos de usuário vencem. Eles vão sempre substituir o estilo definido pelo elemento. Consulte a seção sobre Como criar um elemento que usa o Shadow DOM.
Pré-estimar elementos não registrados
Antes do upgrade de um elemento, você pode segmentá-lo no CSS usando a
pseudoclasse :defined
. Isso é útil para aplicar um estilo predefinido a um componente. Para
por exemplo, você pode querer evitar o layout ou outro FOUC visual ocultando elementos
componentes e esmaecendo-os quando eles são definidos.
Exemplo: oculte <app-drawer>
antes de definir:
app-drawer:not(:defined) {
/* Pre-style, give layout, replicate app-drawer's eventual styles, etc. */
display: inline-block;
height: 100vh;
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
Depois que <app-drawer>
for definido, o seletor (app-drawer:not(:defined)
)
não corresponde mais.
Estender elementos
A API Custom Elements é útil para criar elementos HTML, mas também útil para estender outros elementos personalizados ou até mesmo o HTML integrado do navegador.
Estender um elemento personalizado
A extensão de outro elemento personalizado é feita estendendo sua definição de classe.
Exemplo: crie <fancy-app-drawer>
que estenda <app-drawer>
:
class FancyDrawer extends AppDrawer {
constructor() {
super(); // always call super() first in the constructor. This also calls the extended class' constructor.
// ...
}
toggleDrawer() {
// Possibly different toggle implementation?
// Use ES2015 if you need to call the parent method.
// super.toggleDrawer()
}
anotherMethod() {
// ...
}
}
customElements.define('fancy-app-drawer', FancyDrawer);
Ampliar elementos HTML nativos
Digamos que você queira criar um <button>
mais sofisticado. Em vez de replicar o
comportamento e funcionalidade do <button>
, uma opção melhor é progressivamente
aprimorar o elemento existente usando elementos personalizados.
Um elemento integrado personalizado é um elemento personalizado que estende um dos tags HTML integradas do navegador. O principal benefício de ampliar é ganhar todos os seus recursos (propriedades DOM, métodos, acessibilidade). Não há melhor maneira de criar uma Web Progressiva do que aprimorar progressivamente o HTML existente elementos.
Para estender um elemento, é preciso criar uma definição de classe que herde
da interface DOM correta. Por exemplo, um elemento personalizado que estende
<button>
precisa herdar de HTMLButtonElement
em vez de HTMLElement
.
Da mesma forma, um elemento que estende <img>
precisa estender HTMLImageElement
.
Exemplo - extensão de <button>
:
// See https://html.spec.whatwg.org/multipage/indices.html#element-interfaces
// for the list of other DOM interfaces.
class FancyButton extends HTMLButtonElement {
constructor() {
super(); // always call super() first in the constructor.
this.addEventListener('click', e => this.drawRipple(e.offsetX, e.offsetY));
}
// Material design ripple animation.
drawRipple(x, y) {
let div = document.createElement('div');
div.classList.add('ripple');
this.appendChild(div);
div.style.top = `${y - div.clientHeight/2}px`;
div.style.left = `${x - div.clientWidth/2}px`;
div.style.backgroundColor = 'currentColor';
div.classList.add('run');
div.addEventListener('transitionend', (e) => div.remove());
}
}
customElements.define('fancy-button', FancyButton, {extends: 'button'});
A chamada para define()
muda um pouco ao estender um objeto
. O terceiro parâmetro obrigatório informa ao navegador qual tag está sendo
que se estendem. Isso é necessário porque muitas tags HTML compartilham o mesmo DOM
interface gráfica do usuário. <section>
, <address>
e <em>
(entre outras) compartilham
HTMLElement
<q>
e <blockquote>
compartilham HTMLQuoteElement
; etc...
Especificar {extends: 'blockquote'}
permite que o navegador saiba que você está criando um
<blockquote>
otimizado em vez de um <q>
. Consulte o HTML
spec
para obter a lista completa de interfaces DOM do HTML.
Os consumidores de um elemento integrado personalizado podem usá-lo de várias maneiras. Eles podem
declare-o adicionando o atributo is=""
à tag nativa:
<!-- This <button> is a fancy button. -->
<button is="fancy-button" disabled>Fancy button!</button>
crie uma instância em JavaScript:
// Custom elements overload createElement() to support the is="" attribute.
let button = document.createElement('button', {is: 'fancy-button'});
button.textContent = 'Fancy button!';
button.disabled = true;
document.body.appendChild(button);
ou use o operador new
:
let button = new FancyButton();
button.textContent = 'Fancy button!';
button.disabled = true;
Veja outro exemplo que estende <img>
.
Exemplo - extensão de <img>
:
customElements.define('bigger-img', class extends Image {
// Give img default size if users don't specify.
constructor(width=50, height=50) {
super(width * 10, height * 10);
}
}, {extends: 'img'});
Os usuários declaram esse componente como:
<!-- This <img> is a bigger img. -->
<img is="bigger-img" width="15" height="20">
ou crie uma instância em JavaScript:
const BiggerImage = customElements.get('bigger-img');
const image = new BiggerImage(15, 20); // pass constructor values like so.
console.assert(image.width === 150);
console.assert(image.height === 200);
Detalhes diversos
Elementos desconhecidos x elementos personalizados indefinidos
O HTML é leniente e flexível para trabalhar. Por exemplo, declare
<randomtagthatdoesntexist>
em uma página e o navegador está perfeitamente satisfeito
de aceitá-lo. Por que as tags não padrão funcionam? A resposta é HTML
especificação
que permite. Elementos que não são definidos pela especificação são analisados como
HTMLUnknownElement
:
O mesmo não é verdade para elementos personalizados. Os possíveis elementos personalizados são analisados
como um HTMLElement
se forem criados com um nome válido (incluindo um "-"). Você
pode verificar isso em um navegador compatível com elementos personalizados. Acione o console:
Pressione Ctrl + Shift + J (ou Cmd + Opt + J no Mac) e cole no
as seguintes linhas de código:
// "tabs" is not a valid custom element name
document.createElement('tabs') instanceof HTMLUnknownElement === true
// "x-tabs" is a valid custom element name
document.createElement('x-tabs') instanceof HTMLElement === true
Referência da API
O customElements
global define métodos úteis para trabalhar com dados
os elementos.
define(tagName, constructor, options)
Define um novo elemento personalizado no navegador.
Exemplo
customElements.define('my-app', class extends HTMLElement { ... });
customElements.define(
'fancy-button', class extends HTMLButtonElement { ... }, {extends: 'button'});
get(tagName)
Dado um nome de tag de elemento personalizado válido, retorna o construtor do elemento.
Retornará undefined
se nenhuma definição de elemento tiver sido registrada.
Exemplo
let Drawer = customElements.get('app-drawer');
let drawer = new Drawer();
whenDefined(tagName)
Retorna uma promessa que será resolvida quando o elemento personalizado for definido. Se o elemento já estiver definido, resolva imediatamente. Rejeita a solicitação se o nome da tag não for um nome de elemento personalizado válido.
Exemplo
customElements.whenDefined('app-drawer').then(() => {
console.log('ready!');
});
Histórico e suporte do navegador
Se você acompanhou os componentes da Web nos últimos dois anos,
saber que o Chrome 36+ implementou uma versão da API Custom Elements que usa
document.registerElement()
em vez de customElements.define()
. Agora é
considerada uma versão descontinuada do padrão, chamada v0.
customElements.define()
é a novidade e quais são os fornecedores de navegadores
começar a implementar. Ele é chamado de Custom Elements v1.
Se você tiver interesse na especificação v0 antiga, confira a documentação do html5rocks artigo.
Suporte ao navegador
Chrome 54 (status) Safari 10.1 (status) e O Firefox 63 (status) tem Elementos personalizados v1. O Edge começou no desenvolvimento de software.
Para detectar elementos personalizados, verifique a existência de
window.customElements
:
const supportsCustomElementsV1 = 'customElements' in window;
Polyfill
Até que o suporte a navegadores esteja amplamente disponível, polyfill autônomo (em inglês) disponível para elementos personalizados v1. No entanto, recomendamos usar o pacote webcomponents.js loader para carregar de maneira ideal os polyfills dos componentes da Web. O carregador usa a detecção de recursos para carregar de forma assíncrona somente os Pollyfills necessários exigidos pelo navegador.
Instale:
npm install --save @webcomponents/webcomponentsjs
Uso:
<!-- Use the custom element on the page. -->
<my-element></my-element>
<!-- Load polyfills; note that "loader" will load these async -->
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js" defer></script>
<!-- Load a custom element definitions in `waitFor` and return a promise -->
<script type="module">
function loadScript(src) {
return new Promise(function(resolve, reject) {
const script = document.createElement('script');
script.src = src;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
WebComponents.waitFor(() => {
// At this point we are guaranteed that all required polyfills have
// loaded, and can use web components APIs.
// Next, load element definitions that call `customElements.define`.
// Note: returning a promise causes the custom elements
// polyfill to wait until all definitions are loaded and then upgrade
// the document in one batch, for better performance.
return loadScript('my-element.js');
});
</script>
Conclusão
Os elementos personalizados nos oferecem uma nova ferramenta para definir novas tags HTML no navegador e
criar componentes reutilizáveis. Combine-os com a outra plataforma nova
primitivos, como o Shadow DOM e o <template>
, e começar a perceber os
imagem dos Web Components:
- Compatível com todos os navegadores (padrão da Web) para criar e ampliar componentes reutilizáveis.
- Não exige biblioteca ou framework para começar. JS/HTML comum! UF!
- fornece um modelo de programação familiar; É apenas DOM/CSS/HTML.
- Funciona bem com outros novos recursos da plataforma da Web (shadow DOM,
<template>
, CSS) propriedades personalizadas etc.) - Estreitamente integrado com o DevTools do navegador.
- Aproveite os recursos de acessibilidade atuais.