Les éléments personnalisés permettent aux développeurs Web de définir de nouvelles balises HTML, d'étendre les balises existantes et de créer des composants Web réutilisables.
Avec les éléments personnalisés, les développeurs Web peuvent créer des balises HTML, Complétez les balises HTML existantes ou élargissez les composants dont disposent les autres développeurs. n'est pas rédigée. L'API est à la base du Web composants. Il présente une interface Web standardisé de créer des composants réutilisables en n'utilisant que JS/HTML/CSS vanilla. Résultat : moins de code, de code modulaire et plus de réutilisation nos applications.
Introduction
Le navigateur constitue un excellent outil pour structurer les applications Web. Il est appelée HTML. Vous en avez peut-être entendu parler ! Il est déclaratif, portable, pris en charge et faciles à utiliser. Le langage HTML est très utile, car son vocabulaire et leur extensibilité est limitée. L'expérience HTML vivante standard n'a toujours pas pu associer automatiquement le comportement JS à votre balisage, jusqu'à maintenant.
Les éléments personnalisés sont la solution à la modernisation du code HTML, en comblant les et le regroupement de la structure avec le comportement. Si le code HTML ne fournit pas la solution à un problème, nous pouvons créer un élément personnalisé qui le fait. Personnalisé enseignent de nouvelles astuces au navigateur tout en conservant les avantages du langage HTML.
Définir un nouvel élément
Pour définir un nouvel élément HTML, nous avons besoin de la puissance de JavaScript !
Le global customElements
permet de définir un élément personnalisé et d'enseigner
le navigateur à propos d'un nouveau tag. Appelez customElements.define()
avec le nom de la balise.
que vous souhaitez créer et un class
JavaScript qui étend la HTMLElement
de base.
Exemple – Définition d'un panneau de panneau pour mobile, <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 {...});
Exemple d'utilisation :
<app-drawer></app-drawer>
N'oubliez pas que l'utilisation d'un élément personnalisé n'est pas différente
à l'aide d'un <div>
ou de tout autre élément. Vous pouvez déclarer des instances sur la page,
créés dynamiquement en JavaScript, vous pouvez associer des écouteurs d'événements, etc.
pour découvrir d'autres exemples.
Définir l'API JavaScript d'un élément
La fonctionnalité d'un élément personnalisé est définie à l'aide d'un
class
qui étend HTMLElement
. L'extension de HTMLElement
garantit que l'élément personnalisé
hérite de l'ensemble de l'API DOM, ce qui signifie que toutes les propriétés/méthodes que vous ajoutez
font partie intégrante de l'interface DOM de l'élément. En gros, utilisez la classe pour
créez une API JavaScript publique pour votre tag.
Exemple – Définir l'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);
Dans cet exemple, nous créons un panneau doté de la propriété open
, disabled
.
et une méthode toggleDrawer()
. De plus, il reflète les propriétés au format HTML
Attributs.
Une caractéristique intéressante des éléments personnalisés est que this
dans une définition de classe
fait référence à l'élément DOM lui-même, c'est-à-dire à l'instance de la classe. Dans notre
exemple, this
fait référence à <app-drawer>
. Voilà (😉) Voilà comment l'élément peut
associer un écouteur click
à lui-même ! Vous n'êtes pas limité aux écouteurs d'événements.
L'ensemble de l'API DOM est disponible dans le code de l'élément. Utilisez this
pour accéder à
les propriétés de l'élément, inspecter ses enfants (this.children
), les nœuds de requête
(this.querySelectorAll('.items')
), etc.
Règles relatives à la création d'éléments personnalisés
- Le nom d'un élément personnalisé doit contenir un tiret (-). Donc
<x-tags>
,<my-element>
et<my-awesome-app>
sont des noms valides, tandis que<tabs>
et<foo_bar>
ne le sont pas. Cette exigence permet à l'analyseur HTML de distinguer les éléments personnalisés des éléments standards ; Cela garantit également l’avancement lors de l'ajout de nouvelles balises au code HTML. - Vous ne pouvez pas enregistrer la même balise plusieurs fois. Si vous essayez de le faire,
générer une
DOMException
. Une fois que vous avez signalé un nouveau tag au navigateur, Aucun détournement possible. - Les éléments personnalisés ne peuvent pas se fermer automatiquement, car le code HTML n'autorise que quelques éléments
éléments
se fermer automatiquement. Toujours écrire une balise de fermeture
(
<app-drawer></app-drawer>
).
Réactions d'éléments personnalisés
Un élément personnalisé peut définir des hooks de cycle de vie spéciaux pour exécuter du code pendant des moments intéressants de son existence. Il s'agit d'éléments personnalisés de réaction.
Nom | Appelé lorsque |
---|---|
constructor |
Une instance de l'élément est
créées ou mises à niveau. Utile pour l'initialisation
en configurant des écouteurs d'événements
en créant une "shadow dom".
Consultez le
spec
pour connaître les restrictions sur les actions possibles dans constructor .
|
connectedCallback |
Appelé à chaque fois que la méthode est inséré dans le DOM. Utile pour exécuter du code de configuration, par exemple l'extraction de ressources ou le rendu. En général, vous devez essayer de retarder le travail jusqu'à cette date. |
disconnectedCallback |
Appelé chaque fois que l'élément est supprimé du DOM. Avantages et l'exécution du code de nettoyage. |
attributeChangedCallback(attrName, oldVal, newVal) |
Appelé lorsqu'un attribut observé a été
ajoutées, supprimées, mises à jour ou remplacées. Également appelé pour les valeurs initiales
lorsqu'un élément est créé par l'analyseur ;
mis à niveau. Remarque:uniquement
les attributs listés dans la propriété observedAttributes
recevoir ce rappel.
|
adoptedCallback |
La
élément personnalisé a été déplacé dans un nouveau document (par exemple,
quelqu'un appelé document.adoptNode(el) ).
|
Les rappels de réaction sont synchrones. Si quelqu'un appelle le el.setAttribute()
sur votre élément, le navigateur appelle immédiatement attributeChangedCallback()
.
De même, vous recevrez une disconnectedCallback()
juste après que votre élément soit
supprimé du DOM (par exemple, l'utilisateur appelle el.remove()
).
Exemple:Ajouter des réactions d'éléments personnalisés à <app-drawer>
:
class AppDrawer extends HTMLElement {
constructor() {
super(); // always call super() first in the constructor.
// ...
}
connectedCallback() {
// ...
}
disconnectedCallback() {
// ...
}
attributeChangedCallback(attrName, oldVal, newVal) {
// ...
}
}
Définissez les réactions si elles ont du sens ou quand elles le sont. Si votre élément est suffisamment complexe
et ouvre une connexion à IndexedDB dans connectedCallback()
, effectuez les opérations nécessaires
de nettoyage dans disconnectedCallback()
. Mais faites attention ! Vous ne pouvez pas compter sur
d'être supprimé du DOM en toutes circonstances. Par exemple,
disconnectedCallback()
ne sera jamais appelé si l'utilisateur ferme l'onglet.
Propriétés et attributs
Faire correspondre les propriétés aux attributs
Il n'est pas rare que les propriétés HTML reflètent leur valeur dans le DOM en tant que
HTML. Par exemple, lorsque les valeurs de hidden
ou id
sont modifiées dans
JS:
div.id = 'my-id';
div.hidden = true;
les valeurs sont appliquées au DOM actif en tant qu'attributs:
<div id="my-id" hidden>
C'est ce qu'on appelle "les propriétés "Attributs"". Presque toutes les propriétés en HTML font cela. Pourquoi ? Les attributs sont également utiles pour la configuration d'un élément de manière déclarative et de certaines API, telles que l'accessibilité et les CSS, les sélecteurs s'appuient sur des attributs pour fonctionner.
Le fait de refléter une propriété est utile partout où vous souhaitez conserver le DOM de l'élément la représentation vectorielle continue avec son état JavaScript. Une raison pour laquelle vous pourriez vouloir reflètent une propriété, de sorte que le style défini par l'utilisateur s'applique lorsque l'état JS change.
Rappelez-vous notre <app-drawer>
. Un consommateur de ce composant peut vouloir le masquer en fondu
et/ou empêcher toute interaction de l'utilisateur lorsqu'elle est désactivée:
app-drawer[disabled] {
opacity: 0.5;
pointer-events: none;
}
Lorsque la propriété disabled
est modifiée en JavaScript, cet attribut doit être
ajouté au DOM pour que
le sélecteur de l'utilisateur corresponde. L'élément peut fournir que
comportement en reflétant la valeur d'un attribut du même nom:
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();
}
Observer les modifications apportées aux attributs
Les attributs HTML sont un moyen pratique pour les utilisateurs de déclarer un état initial:
<app-drawer open disabled></app-drawer>
Les éléments peuvent réagir aux modifications d'attributs en définissant un
attributeChangedCallback
Le navigateur appelle cette méthode pour chaque modification
aux attributs listés dans le tableau 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.
}
}
Dans l'exemple, nous définissons des attributs supplémentaires sur <app-drawer>
lorsqu'un
L'attribut disabled
a été modifié. Bien que nous ne le fassions pas ici, vous pouvez
utilisez également attributeChangedCallback
pour synchroniser une propriété JavaScript avec son
.
Mises à niveau d'éléments
Code HTML progressivement amélioré
Nous avons déjà vu que les éléments
personnalisés sont définis en appelant
customElements.define()
Cela ne signifie pas pour autant que vous devez définir et enregistrer
d'un élément personnalisé.
Les éléments personnalisés peuvent être utilisés avant que leur définition ne soit enregistrée.
L'amélioration progressive est une fonctionnalité d'éléments personnalisés. En d'autres termes, vous pouvez
déclarer un ensemble d'éléments <app-drawer>
sur la page et ne jamais appeler
customElements.define('app-drawer', ...)
et bien plus tard. En effet,
le navigateur traite les éléments personnalisés potentiels différemment en raison de la valeur inconnu
tags. Processus consistant à appeler define()
et à attribuer un élément
avec une définition de classe s'appelle "mises à niveau d'éléments".
Pour savoir quand le nom d'une balise est défini, vous pouvez utiliser
window.customElements.whenDefined()
Elle renvoie une promesse qui se résout lorsque le
est défini.
customElements.whenDefined('app-drawer').then(() => {
console.log('app-drawer defined');
});
Exemple : retarder le travail jusqu'à ce qu'un ensemble d'éléments enfants soit mis à niveau
<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.
});
Contenu défini par l'élément
Les éléments personnalisés peuvent gérer leur propre contenu à l'aide des API DOM qu'ils contiennent. du code de l'élément. Les réactions sont très utiles à cet effet.
Exemple – Créez un élément avec du code HTML par défaut:
customElements.define('x-foo-with-markup', class extends HTMLElement {
connectedCallback() {
this.innerHTML = "<b>I'm an x-foo-with-markup!</b>";
}
// ...
});
La déclaration de cette balise produit:
<x-foo-with-markup>
<b>I'm an x-foo-with-markup!</b>
</x-foo-with-markup>
// À FAIRE: DevSite - Exemple de code supprimé, car il utilisait des gestionnaires d'événements intégrés
Créer un élément qui utilise Shadow DOM
Shadow DOM permet à un élément de posséder, d'afficher et de styliser un fragment de un DOM distinct du reste de la page. Mince, vous pourriez même cacher un l'intégralité de l'application à l'aide d'une seule balise:
<!-- chat-app's implementation details are hidden away in Shadow DOM. -->
<chat-app></chat-app>
Pour utiliser un Shadow DOM dans un élément personnalisé, appelez this.attachShadow
dans votre
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));
}
// ...
});
Exemple d'utilisation :
<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>
Texte personnalisé de l'utilisateur
// À FAIRE: DevSite - Exemple de code supprimé, car il utilisait des gestionnaires d'événements intégrés
Créer des éléments à partir d'un <template>
Pour les utilisateurs inconnus, le <template>
vous permet de déclarer des fragments du DOM qui sont analysés, inertes lors du chargement de la page et
peuvent être activées ultérieurement au moment de l'exécution. Il s'agit d'une autre primitive de l'API sur le Web.
la famille de composants. Les modèles constituent un espace réservé idéal pour déclarer
la structure d'un élément personnalisé.
Exemple:enregistrer un élément avec du contenu Shadow DOM créé à partir d'un
<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>
Ces quelques lignes de code sont particulièrement intéressantes. Voyons les principaux éléments sur:
- Nous définissons un nouvel élément dans le code HTML:
<x-foo-from-template>
- Le Shadow DOM de l'élément est créé à partir d'un
<template>
. - Le DOM de l'élément est propre à l'élément grâce au Shadow DOM
- Le code CSS interne de l'élément est limité à celui-ci grâce au Shadow DOM
Je suis dans Shadow DOM. Mon balisage est basé sur un élément <template>.
// À FAIRE: DevSite - Exemple de code supprimé, car il utilisait des gestionnaires d'événements intégrés
Appliquer un style à un élément personnalisé
Même si votre élément définit son propre style à l'aide de Shadow DOM, les utilisateurs peuvent appliquer votre élément personnalisé sur leur page. Ceux-ci sont appelés "styles définis par l'utilisateur".
<!-- 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>
Vous vous demandez peut-être comment fonctionne la spécificité CSS si l'élément a des styles défini dans Shadow DOM. En termes de spécificité, les styles d’utilisateur l’emportent. Il remplacez toujours le style défini par l'élément. Consultez la section Créer un élément qui utilise le Shadow DOM.
Préconfigurer des éléments non enregistrés
Avant de mettre à jour un élément, vous pouvez le cibler en CSS à l'aide de la méthode
Pseudo-classe :defined
. Cela est utile pour préstyliser un composant. Pour
Par exemple, vous pouvez empêcher la mise en page ou tout autre élément visuel FOUC en masquant les données
des composants et de les faire apparaître
en fondu lorsqu'ils sont définis.
Exemple – Masquer la valeur <app-drawer>
avant qu'elle soit définie:
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;
}
Une fois <app-drawer>
défini, le sélecteur (app-drawer:not(:defined)
)
ne correspond plus.
Extension des éléments
L'API Custom Elements est utile pour créer des éléments HTML, utile pour étendre d'autres éléments personnalisés ou même le code HTML intégré au navigateur.
Étendre un élément personnalisé
Pour étendre un autre élément personnalisé, vous devez étendre sa définition de classe.
Exemple – Créez <fancy-app-drawer>
qui étend <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);
Étendre les éléments HTML natifs
Imaginons que vous souhaitiez créer un <button>
plus sophistiqué. Au lieu de répliquer
le comportement et les fonctionnalités de <button>
, une meilleure option consiste à
améliorer l'élément existant à l'aide d'éléments personnalisés.
Un élément intégré personnalisé est un élément personnalisé qui étend l'un des les tags HTML intégrés au navigateur. Le principal avantage de l'extension est d'obtenir toutes ses fonctionnalités (propriétés DOM, méthodes, accessibilité). Il n'existe pas de meilleure façon de rédiger un Web progressif application que d'améliorer progressivement le code HTML existant .
Pour étendre un élément, vous devez créer une définition de classe qui hérite
dans la bonne interface DOM. Par exemple, un élément personnalisé qui s'étend
<button>
doit hériter de HTMLButtonElement
au lieu de HTMLElement
.
De même, un élément qui étend <img>
doit étendre HTMLImageElement
.
Exemple – Extension 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'});
Notez que l'appel à define()
change légèrement lors de l'extension d'une annonce native.
. Le troisième paramètre, qui est obligatoire, indique au navigateur
l'extension. Cette étape est nécessaire, car de nombreuses balises HTML partagent le même DOM
de commande. <section>
, <address>
et <em>
(entre autres) partagent tous
HTMLElement
; <q>
et <blockquote>
partagent tous deux HTMLQuoteElement
; etc.
En spécifiant {extends: 'blockquote'}
, vous indiquez au navigateur que vous créez un
<blockquote>
a augmenté au lieu d'une <q>
. Consultez le code HTML
spec
pour obtenir la liste complète des interfaces DOM HTML.
Les utilisateurs d'un élément intégré personnalisé peuvent l'utiliser de différentes manières. Ils peuvent
Déclarez-la en ajoutant l'attribut is=""
à la balise native:
<!-- This <button> is a fancy button. -->
<button is="fancy-button" disabled>Fancy button!</button>
créez une instance en 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);
Vous pouvez également utiliser l'opérateur new
:
let button = new FancyButton();
button.textContent = 'Fancy button!';
button.disabled = true;
Voici un autre exemple qui étend <img>
.
Exemple – Extension 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'});
Les utilisateurs déclarent ce composant en tant que:
<!-- This <img> is a bigger img. -->
<img is="bigger-img" width="15" height="20">
ou créez une instance en 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);
Détails divers
Éléments inconnus et éléments personnalisés non définis
Le langage HTML est indulgent et flexible. Par exemple, déclarez
<randomtagthatdoesntexist>
sur une page et le navigateur est parfaitement satisfait
de l'accepter. Pourquoi les tags non standards fonctionnent-ils ? La réponse est le HTML
caractéristiques
le permet. Les éléments qui ne sont pas définis par la spécification sont analysés comme
HTMLUnknownElement
Il en va de même pour les éléments personnalisés. Les éléments personnalisés potentiels sont analysés
en tant que HTMLElement
s'ils sont créés avec un nom valide (inclut un "-"). Toi
vous pouvez le vérifier dans un navigateur
compatible avec les éléments personnalisés. Démarrez la console:
Ctrl+Maj+J (ou Cmd+Opt+J sur Mac) et coller la
les lignes de code suivantes:
// "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
Documentation de référence de l'API
Le global customElements
définit des méthodes utiles pour utiliser des
éléments.
define(tagName, constructor, options)
Définit un nouvel élément personnalisé dans le navigateur.
Exemple
customElements.define('my-app', class extends HTMLElement { ... });
customElements.define(
'fancy-button', class extends HTMLButtonElement { ... }, {extends: 'button'});
get(tagName)
Si un nom de balise d'élément personnalisé valide est fourni, renvoie le constructeur de l'élément.
Renvoie undefined
si aucune définition d'élément n'a été enregistrée.
Exemple
let Drawer = customElements.get('app-drawer');
let drawer = new Drawer();
whenDefined(tagName)
Affiche une promesse qui se résout lorsque l'élément personnalisé est défini. Si le est déjà défini, résolvez-le immédiatement. Rejeté si le nom de la balise n'est pas un nom d'élément personnalisé valide.
Exemple
customElements.whenDefined('app-drawer').then(() => {
console.log('ready!');
});
Historique et navigateurs compatibles
Si vous suivez les composants Web
depuis les deux dernières années, vous
sachez que Chrome 36 ou version ultérieure a mis en œuvre une version de l'API Custom Elements qui utilise
document.registerElement()
au lieu de customElements.define()
. C'est maintenant
considéré comme une version obsolète
de la norme, appelée v0.
customElements.define()
est la nouvelle tendance et les fournisseurs de navigateurs
à mettre en œuvre. Il s'agit de Custom Elements v1.
Si l'ancienne spécification V0 vous intéresse, consultez le document html5rocks pour en savoir plus.
Prise en charge des navigateurs
Chrome 54 (état), Safari 10.1 (état) et Firefox 63 (état) ont Custom Elements v1 Edge a commencé développement d'applications.
Pour détecter des éléments personnalisés, vérifiez l'existence des éléments suivants :
window.customElements
:
const supportsCustomElementsV1 = 'customElements' in window;
Polyfill
En attendant que les navigateurs soient pris en charge, polyfill autonome disponibles pour Custom Elements v1. Toutefois, nous vous recommandons d'utiliser le fichier webcomponents.js loader pour charger de façon optimale les polyfills des composants Web. Chargeur utilise la détection de fonctionnalités pour ne charger de manière asynchrone que les pollyfills nécessaires requise par le navigateur.
Installez-la:
npm install --save @webcomponents/webcomponentsjs
Utilisation :
<!-- 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>
Conclusion
Les éléments personnalisés constituent un nouvel outil pour définir de nouvelles balises HTML dans le navigateur et
créer des composants réutilisables. Associez-les à l'autre nouvelle plate-forme
primitives telles que Shadow DOM et <template>
, et nous commençons à réaliser
image des composants Web:
- Utilisation multi-navigateurs (norme Web) pour créer et développer des composants réutilisables
- Vous n'avez besoin d'aucune bibliothèque ni aucun framework pour vous lancer. Vanilla JS/HTML FTW!
- Il fournit un modèle de programmation familier. Il s'agit simplement du DOM/CSS/HTML.
- Compatible avec les autres nouvelles fonctionnalités de la plate-forme Web (Shadow DOM,
<template>
et CSS) propriétés personnalisées, etc.) - Étroitement intégré aux outils de développement du navigateur
- Exploitez les fonctionnalités d'accessibilité existantes.