javascript 如何获取已注册的自定义元素列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27334365/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 07:21:07  来源:igfitidea点击:

How to get list of registered custom elements

javascripthtmlw3cweb-componentcustom-element

提问by dy_

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?

我有document.registerElement,但还有什么?它是单向 API 吗?

回答by Aleksei Matiushkin

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

有一种方法可以检查元素是否已注册。已注册的元素有自己的构造函数,而未注册的元素将使用普通HTMLElement()的构造函数(或者HTMLUnknownElement()名称是否无效,但这超出了问题的范围):

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.

AFAIK 无法访问已注册元素列表。

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

顺便说一句,我仍然认为try-catched注册(由@stephan-muller 提出)更适合您的需求。

回答by Rico Kahler

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

由于自定义元素现在是最新标准的一部分,我想我会在 2017 年以上分享如何做到这一点:

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

注意:该document.registerElement函数已被弃用,取而代之的是 customElements.define()。

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

customElements被定义为 中的全局变量window定义了三种方法

  1. define
  2. get
  3. whenDefined
  1. define
  2. get
  3. whenDefined

getis the important one here. gettakes a stringof the element name and returns the constructor for the named custom element, or undefinedif there is no custom element definition for the name.

get是这里很重要的一个。get获取string元素名称的 a 并返回命名的自定义元素的构造函数,或者undefined如果名称没有自定义元素定义。

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

因此,在 2017+ 年,要检查元素是否已注册,您是否:

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

注意:这在 IE 中不起作用。请参阅此处了解浏览器兼容性

回答by Paul Irish

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

enter image description here

在此处输入图片说明

回答by Stephan Muller

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...catchblock:

目前似乎没有办法查看所有已注册的元素,但有一种方法可以检查元素是否已注册:将寄存器包装在一个try...catch块中:

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.

如果您只是想检查它是否已注册,这确实有一个缺点:如果没有,它将在运行后进行。似乎也没有办法取消注册元素。

回答by Fuzzical Logic

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

虽然我不确定它是否适用于其他 Web 组件框架,但在 Chrome 中使用 Polymer 时,我有一个CustomElements对象指向该window对象。该CustomElements对象具有所有注册的自定义元素的键/值集合,称为registry

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

回答by lzzluca

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

正如已经在 Polymer 的 Slack 频道上写的那样,这是一个可以完成这项工作的肮脏的频道:

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

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

不确定多少Polumer.telemetry.registrations是可靠的(在文档上没有看到)并且Array.prototype.find不是跨浏览器!

回答by Markus

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

在自定义元素类(构造函数)自注册元素的情况下,检查该类是否存在就足够了