web-dev-qa-db-fra.com

Comment obtenir la liste des éléments personnalisés enregistrés

J'essaie de détecter si un élément personnalisé avec un nom spécifique a été enregistré ou non. Y at-il un moyen de faire une telle vérification?

Ou existe-t-il un moyen d'obtenir une liste des éléments personnalisés enregistrés?

Je fais document.registerElement, mais qu'y a-t-il d'autre? Est-ce une API à sens unique?

33
dy_

Il existe un moyen de vérifier si un élément a été enregistré. Les éléments enregistrés ont leurs propres constructeurs, alors que les éléments non enregistrés utiliseraient HTMLElement() pour constructeur (ou HTMLUnknownElement() si le nom n'est pas valide, mais cela sort du champ de la question):

document.registerElement('x-my-element');
document.createElement('x-my-element').constructor
//⇒ function x-my-element() { [native code] }
document.createElement('x-my-element-not-registered').constructor
//⇒ function HTMLElement() { [native code] }

Cela dit, le vérificateur pourrait ressembler à:

var isRegistered = function(name) {
  return document.createElement(name).constructor !== HTMLElement;
}

Ou, avec du sucre syntaxique:

String.prototype.isRegistered = function() { 
  return document.createElement(this).constructor !== HTMLElement; 
}
'x-my-element'.isRegistered()
//⇒ true
'xx-my-element'.isRegistered()
//⇒ false

La version la plus prudente:

String.prototype.wasRegistered = function() { 
  switch(document.createElement(this).constructor) {
    case HTMLElement: return false; 
    case HTMLUnknownElement: return undefined; 
  }
  return true;
}
'x-my-element'.wasRegistered()
//⇒ true
'xx-my-element'.wasRegistered()
//⇒ false
'xx'.wasRegistered()
//⇒ undefined

Il n’existe aucun moyen d’accéder à une liste d’éléments enregistrés, autant que je sache.

Au fait, je pense toujours que l'enregistrement try-catched (proposé par @ stephan-muller) répond mieux à vos besoins.

43
Aleksei Matiushkin

En combinant quelques-unes des approches ci-dessus, vous pouvez parcourir tout ce qui est utilisé et créer une liste unique d'éléments personnalisés (et enregistrés):

function isRegistered(name) {
  return document.createElement(name).constructor.__proto__ !== window.HTMLElement;
}

var allElems = document.querySelectorAll('html /deep/ *');
var nodeNames = [].map.call(allElems, el => el.nodeName.toLowerCase())
                    .filter((value, index, self) => self.indexOf(value) === index)

console.log('all elements', nodeNames);
console.log('registered, custom elements', nodeNames.filter(isRegistered))

 enter image description here

17
Paul Irish

Étant donné que les éléments personnalisés font maintenant partie de la dernière norme , je pensais que je partagerais comment faire cela en 2017+:

Remarque: la fonction document.registerElement a été obsolète en faveur de customElements.define ().

customElements est défini comme global dans window. Trois méthodes sont définies :

  1. define
  2. get
  3. whenDefined

get est le plus important ici. get prend une string du nom de l'élément et retourne le constructeur de l'élément personnalisé nommé, ou undefined s'il n'y a pas de définition d'élément personnalisé pour le nom.

Donc en 2017+ pour vérifier si un élément a été enregistré faites-vous:

const myElementExists = !!customElements.get('my-element');

Cependant, je ne sais pas s'il est possible d'obtenir une liste d'éléments définis. Il est également important de noter que Chrome est le seul navigateur qui définit cela de manière native à ce stade. CustomElements v1 fait partie de la norme et ne fait donc pas partie de Polymer si quelqu'un se le demandait mais ils l'ont fait ont fait un polyfill pour cela .

15
Rico Kahler

Il ne semble pas qu'il soit possible de voir tous les éléments enregistrés pour le moment, mais il existe un moyen de vérifier si un élément a déjà été enregistré ou non: placer le registre dans un bloc try...catch:

try {
    document.registerElement('x-my-element');
} catch(e) {
    console.log('already exists', e);
}

Exécutez ceci deux fois dans votre console et l'erreur d'erreur sera consignée. 

Cela a un inconvénient si vous voulez simplement vérifier si le fichier a bien été enregistré: si ce n’est pas le cas, ce sera après avoir exécuté ceci. Il semble également qu'il n'y ait pas moyen de désenregistrer un élément.

10
Stephan Muller

Bien que je ne sois pas sûr que cela s'applique à d'autres frameworks de composants Web, lors de l'utilisation de Polymer dans Chrome, j'ai un objet CustomElements dans l'objet window. L'objet CustomElements a une collection clé/valeur de tous les éléments personnalisés enregistrés appelée registry.

function isRegistered(name) {
    if (window.CustomElements && window.CustomElements.registry)
        return name in window.CustomElements.registry;
    return undefined;
}
7
Fuzzical Logic

Comme déjà écrit sur le canal Slack de Polymer, c'est un sale qui peut faire le travail:

function isElementRegistered(elementId) {
  return Polymer.telemetry.registrations.find(function(item) { return item.is === elementId })
}

Vous ne savez pas combien Polumer.telemetry.registrations est fiable (vous ne l'avez pas vu dans la doc) et Array.prototype.find n'est pas inter-navigateur!

3
lzzluca

dans les scénarios où les classes d'éléments personnalisés (constructeurs) auto-enregistrent un élément, il suffit de vérifier la présence de la classe

1
Markus