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

Javascript 如何获取已注册自定义元素的列表,javascript,html,w3c,web-component,custom-element,Javascript,Html,W3c,Web Component,Custom Element,我试图检测是否注册了具有特定名称的自定义元素。有没有办法做这样的检查 或者有没有一种方法可以获取已注册自定义元素的列表 我不知道document.registerement,但是还有什么?它是单向API吗?目前似乎没有办法查看所有已注册的元素,但有一种方法可以检查元素是否已注册:将寄存器包装在try…catch块中: try { document.registerElement('x-my-element'); } catch(e) { console.log('already

我试图检测是否注册了具有特定名称的自定义元素。有没有办法做这样的检查

或者有没有一种方法可以获取已注册自定义元素的列表


我不知道document.registerement,但是还有什么?它是单向API吗?

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

try {
    document.registerElement('x-my-element');
} catch(e) {
    console.log('already exists', e);
}
在控制台中运行两次,您将看到记录的错误


但是,如果您只是想检查它是否已注册,那么这确实有一个缺点:如果未注册,则将在运行此操作后注册。似乎也没有办法注销元素。

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

也就是说,检查器可能看起来像:

var isRegistered = function(name) {
  return document.createElement(name).constructor !== HTMLElement;
}
或者,使用语法糖:

String.prototype.isRegistered = function() { 
  return document.createElement(this).constructor !== HTMLElement; 
}
'x-my-element'.isRegistered()
//⇒ true
'xx-my-element'.isRegistered()
//⇒ false
最谨慎的版本是:

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
无法访问已注册元素的列表,AFAIK


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

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

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

结合上述几种方法,您可以迭代使用中的所有内容,并生成自定义(和注册)元素的唯一列表:

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

正如已经在聚合物的松弛通道上写的那样,这是一个肮脏的通道,可以完成工作:

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

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

由于自定义元素现在是的一部分,我想在2017+中分享一下如何做到这一点:

注意:
document.registerement
功能已被禁用

customElements
窗口中定义为全局元素

  • 定义
  • get
  • 定义时
  • get
    是这里最重要的一个
    get
    获取元素名称的
    字符串
    ,并返回命名自定义元素的构造函数,如果名称没有自定义元素定义,则返回
    undefined

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

    const myElementExists = !!customElements.get('my-element');
    
    但是,我不确定是否有办法获得已定义元素的列表



    注意:这在IE中不起作用。

    在自定义元素类(构造函数)自注册元素的场景中,检查类的存在就足够了。

    以下是使用ES6获取所有已注册的
    自定义元素列表的一种方法

    //获取所有元素
    const elements=document.querySelectorAll(“*”)
    //从元素创建数组
    常量elementArray=Array.from(元素)
    //映射到节点名称
    const nodeName=elementArray.map(element=>element.nodeName.toLowerCase())
    //注册的过滤器
    const allCustomElementNames=nodeNames.filter(customElements.get.bind(customElements))
    
    我不确定我的答案是否更适合他的需要,但这是一个很好的答案,提供了有用的附加信息。谢谢我很高兴你发现这个答案很有用。很好的答案。只是要小心,在测试一个元素是否已注册时,
    document.createElement(name).constructor
    part实际上会创建该元素(如果该元素已注册),并且您可能会发现自己正在搜索聚合元素的就绪事件触发两次的原因:)@synk上面的检查与操作系统无关。它只依赖于浏览器。这似乎是聚合物跟踪它注册的元素的结果。由于缺少获取自定义注册元素列表的本地方法,因此在注册新元素时自己跟踪它们实际上是一个好主意。然而,这并没有必要解决这里的原始问题,因为从这个问题来看,不清楚他是否自己注册元素。他的应用程序中可能包含一些库/框架,这些库/框架在不跟踪的情况下进行注册。同意。我只是认为它可能对其他人有帮助,因为一些聚合物用户可能会在这里结束。有趣的是,
    页眉
    ,和
    页脚
    也是“自定义的”元素,即使它们是本机HTML5元素。
    Uncaught DomeException:未能对“文档”执行“querySelectorAll”:“html/deep/*”不是有效的选择器。在:1:25时,将不显示未实例化或分离的元素
    
    const myElementExists = !!customElements.get('my-element');