How to get list of registered custom elements

前端 未结 7 527
萌比男神i
萌比男神i 2020-12-08 09:55

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 regist

相关标签:
7条回答
  • 2020-12-08 10:18

    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;
    }
    
    0 讨论(0)
  • 2020-12-08 10:20

    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.


    NOTE: this doesn't work in IE. See here for browser compatibility

    0 讨论(0)
  • 2020-12-08 10:24

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

    0 讨论(0)
  • 2020-12-08 10:33

    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.

    0 讨论(0)
  • 2020-12-08 10:33

    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!

    0 讨论(0)
  • 2020-12-08 10:35

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

    0 讨论(0)
提交回复
热议问题