2014-12-06 47 views
26

我试图检测具有特定名称的自定义元素是否已注册。有没有办法做这样的检查?如何获取已注册的自定义元素列表

或者有没有办法获得已注册的自定义元素列表?

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

回答

36

有一种方法来检查元素是否被注册。注册元素都有自己的构造函数,而未经注册的人会用构造简单的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] } 

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

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的列表。

顺便说一句,我仍然认为尝试捕获注册(由@ stephan-muller提议)更适合您的需求。

+1

的存在我不知道如果我的回答适合他的需求更好,但是这是一个有用的附加信息很好的答案。谢谢! – 2015-02-01 15:54:17

+0

我很高兴你找到了有用的答案。 – mudasobwa 2015-02-02 09:50:39

+0

很好的答案。在测试一个元素是否被注册的时候要小心,'document.createElement(name).constructor'部分实际上创建了元素(如果它已经被注册了),并且你会发现你正在搜索你的Polymer元素的准备事件为什么会两次发射:) – 2016-11-26 19:49:31

10

目前似乎没有办法看到所有已注册的元素的那一刻,但有一个方法来检查是否一个元素已经被登记:包裹寄存在try...catch块:

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

在控制台中运行两次,您将看到记录的错误。

这确实有一个缺点,如果你只是想检查它是否被注册,但:如果它不是,它会在运行后。也没有办法注销一个看起来像的元素。

7

尽管我不确定它适用于其他Web组件框架,但在Chrome中使用Polymer时,我有一个CustomElements对象与window对象。 CustomElements对象具有名为registry的所有已注册自定义元素的键/值集合。

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

看来,这是Polymer记录它注册哪些元素的结果。鉴于缺乏获取自定义注册元素列表的本地方法,在注册新元素的同时自己跟踪它们实际上是一个好主意。然而,这并不需要解决这里的原始问题,因为从他是否自己注册元素的问题来看并不清楚。他的应用程序中可能包含一些图书馆/框架,用于注册而不保持跟踪。 – 2015-02-01 15:56:24

+0

同意。只是认为它可能对其他人看起来很有用,因为一些Polymer用户可能会在这里结束。 – 2015-02-02 01:53:14

7

结合几个上述方法可以遍历使用一切,吐出定制的唯一列表(和注册)元素:

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

2

由于已经写在聚合物的松弛通道上,这是一个肮脏的,可以使工作:

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

不知道多少Polumer.telemetry.registrations是可靠的(没有看到它的文档)和Array.prototype.find是不是跨浏览器!

8

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

注:document.registerElement功能已经deprecated in favor of customElements.define().

customElements定义作为全球windowThere are three methods defined

  1. define
  2. get

get是这里最重要的一个。 get需要元素名称的string,并返回指定的自定义元素的构造函数,如果没有该名称的自定义元素定义,则返回undefined

所以在2017+到检查元素是否已经注册你:

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

我不知道是否有一种方式来获得定义元素的列表但是。同样重要的是要注意,chrome是目前在本地定义此唯一浏览器的唯一浏览器。 CustomElements v1是标准的一部分,所以如果有人想知道这不是聚合物的一部分,但他们确实是make a polyfill for it

0
在场景

其中定制元素类(构造函数)自行注册的元素,就足够了检查类