textcontent style ejemplos ejemplo attribute javascript html5 w3c web-component custom-element

javascript - style - Cómo obtener la lista de elementos personalizados registrados



title css (7)

Estoy tratando de detectar si un elemento personalizado con un nombre específico fue registrado o no. ¿Hay alguna manera de hacer tal comprobación?

¿O hay una manera de obtener una lista de elementos personalizados registrados?

Hago document.registerElement , pero ¿qué más hay? ¿Es unidireccional API?


Aunque no estoy seguro de que se aplique a otros marcos de componentes web, mientras uso Polymer en Chrome, tengo un objeto CustomElements para el objeto de window . El objeto CustomElements tiene una colección de clave / valor de todos los elementos personalizados registrados llamados registry .

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


Combinando algunos de los enfoques anteriores, puede iterar sobre todo en uso y escupir una lista única de elementos personalizados (y registrados):

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))


Como ya se escribió en el canal Slack del polímero, este es un sucio que puede hacer el trabajo:

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

Sin embargo, no estoy seguro de cuánto es fiable (no lo he visto en el documento) de Array.prototype.find y Array.prototype.find no es un navegador cruzado.


Hay una manera de verificar si un elemento fue registrado. Los elementos registrados tienen sus propios constructores, mientras que los no registrados usarían HTMLElement() para el constructor (o HTMLUnknownElement() si el nombre no es válido, pero esto está fuera del alcance de la pregunta):

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] }

Dicho esto, el verificador podría verse como:

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

O bien, con azúcar sintáctica:

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

La versión mayormente cuidadosa:

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

No hay forma de acceder a una lista de elementos registrados, AFAIK.

Por cierto, sigo pensando que el registro try-catched (según lo propuesto por @ stephan-muller) se adapta mejor a sus necesidades.


Parece que no hay una manera de ver todos los elementos registrados en este momento, pero hay una manera de verificar si un elemento ya se ha registrado o no: envuelva el registro en un bloque try...catch :

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

Ejecuta esto dos veces en tu consola y verás el error registrado.

Sin embargo, esto tiene un inconveniente si simplemente quiere verificar si se registró o no: si no fue así, será después de ejecutar esto. Tampoco hay una manera de anular el registro de un elemento que parece.


Ya que los elementos personalizados son ahora parte del último estándar , pensé que compartiría cómo hacer esto en 2017+:

Nota: la función document.registerElement ha quedado en desuso en favor de customElements.define ().

customElements se define como un global en la window . Hay tres métodos definidos :

  1. define
  2. get
  3. whenDefined

get es el importante aquí. get toma una string del nombre del elemento y devuelve el constructor para el elemento personalizado nombrado, o undefined si no existe una definición de elemento personalizado para el nombre.

Entonces en 2017+ para verificar si un elemento ha sido registrado, usted:

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

No estoy seguro si hay una manera de obtener una lista de elementos definidos sin embargo. También es importante tener en cuenta que Chrome es el único navegador que lo define de forma nativa en este momento. CustomElements v1 es parte de la norma, por lo que esto no es parte de Polymer si alguien se lo preguntaba, pero hicieron un polyfill para él .


en escenarios donde las clases de elementos personalizados (constructores) autorregistran un elemento, es suficiente para verificar la presencia de la clase