How to get list of registered custom elements

一笑奈何 提交于 2019-12-18 11:06:56

问题


I'm trying to detect whether a custom element with a specific name was registered or not. Is there a way to make such check?

Or is there a way to get list of registered custom elements?

I do document.registerElement, but what else is there? Is it one-way API?


回答1:


There is a way to check whether an element was registered. Registered elements have their own constructors, while unregistered ones would use plain HTMLElement() for constructor (or HTMLUnknownElement() whether the name is not valid, but this is out of scope of the 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] }

That said, the checker might look like:

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

Or, with syntactic sugar:

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

The mostly careful version:

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

There is no way to access a list of registered elements, AFAIK.

BTW, I still think that the try-catched registration (as proposed by @stephan-muller) suits your needs better.




回答2:


Combining a few of the above approaches you can iterate over everything in use and spit out a unique list of custom (and registered) elements:

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




回答3:


Since custom elements is now part of the latest standard, I thought I'd share how to do this in 2017+:

Note: the document.registerElement function has been deprecated in favor of customElements.define().

customElements is defined as a global in window. There are three methods defined:

  1. define
  2. get
  3. whenDefined

get is the important one here. get takes a string of the element name and returns the constructor for the named custom element, or undefined if there is no custom element definition for the name.

So in 2017+ to check if an element has been registered do you:

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

I'm not sure if there's a way to get a list of defined elements however. It's also important to note that chrome is the only browser that defines this natively at this point in time. CustomElements v1 are part of the standard so this isn't part of Polymer if anyone was wondering but they did make a polyfill for it.




回答4:


There doesn't seem to a way to see all registered elements at the moment, but there is a way to check whether or not an element has been registered already: wrap the register in a try...catch block:

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

Run this twice in your console and you'll see the error logged.

This does have a drawback if you simply want to check whether or not it was registered though: if it was not, it will be after running this. There also isn't a way to unregister an element it seems.




回答5:


While I am not sure it applies to other Web Component frameworks, while using Polymer in Chrome, I have a CustomElements object to the window object. The CustomElements object has a key/value collection of all registered custom elements called registry.

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



回答6:


As written already on the Polymer's Slack channel, this is a dirty one that can make the job:

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

Not sure how much Polumer.telemetry.registrations is reliable though (haven't seen it on the doc) and Array.prototype.find is not cross-browser!




回答7:


in scenarios where custom element classes (constructors) self-register an element, it is sufficient to check for the presence of the class



来源:https://stackoverflow.com/questions/27334365/how-to-get-list-of-registered-custom-elements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!