我试图检测具有特定名称的自定义元素是否已注册。有没有办法做这样的检查?如何获取已注册的自定义元素列表
或者有没有办法获得已注册的自定义元素列表?
我是document.registerElement
,但还有什么?它是单向API吗?
我试图检测具有特定名称的自定义元素是否已注册。有没有办法做这样的检查?如何获取已注册的自定义元素列表
或者有没有办法获得已注册的自定义元素列表?
我是document.registerElement
,但还有什么?它是单向API吗?
有一种方法来检查元素是否被注册。注册元素都有自己的构造函数,而未经注册的人会用构造简单的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提议)更适合您的需求。
目前似乎没有办法看到所有已注册的元素的那一刻,但有一个方法来检查是否一个元素已经被登记:包裹寄存在try...catch
块:
try {
document.registerElement('x-my-element');
} catch(e) {
console.log('already exists', e);
}
在控制台中运行两次,您将看到记录的错误。
这确实有一个缺点,如果你只是想检查它是否被注册,但:如果它不是,它会在运行后。也没有办法注销一个看起来像的元素。
尽管我不确定它适用于其他Web组件框架,但在Chrome中使用Polymer时,我有一个CustomElements
对象与window
对象。 CustomElements
对象具有名为registry
的所有已注册自定义元素的键/值集合。
function isRegistered(name) {
if (window.CustomElements && window.CustomElements.registry)
return name in window.CustomElements.registry;
return undefined;
}
看来,这是Polymer记录它注册哪些元素的结果。鉴于缺乏获取自定义注册元素列表的本地方法,在注册新元素的同时自己跟踪它们实际上是一个好主意。然而,这并不需要解决这里的原始问题,因为从他是否自己注册元素的问题来看并不清楚。他的应用程序中可能包含一些图书馆/框架,用于注册而不保持跟踪。 – 2015-02-01 15:56:24
同意。只是认为它可能对其他人看起来很有用,因为一些Polymer用户可能会在这里结束。 – 2015-02-02 01:53:14
结合几个上述方法可以遍历使用一切,吐出定制的唯一列表(和注册)元素:
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
是不是跨浏览器!
由于自定义元素现在是the latest standard一部分,我想我会分享如何做到这一点的2017+:
注:
document.registerElement
功能已经deprecated in favor of customElements.define().
customElements
定义作为全球window
。 There are three methods defined:
define
get
get
是这里最重要的一个。 get
需要元素名称的string
,并返回指定的自定义元素的构造函数,如果没有该名称的自定义元素定义,则返回undefined
。
所以在2017+到检查元素是否已经注册你:
const myElementExists = !!customElements.get('my-element');
我不知道是否有一种方式来获得定义元素的列表但是。同样重要的是要注意,chrome是目前在本地定义此唯一浏览器的唯一浏览器。 CustomElements v1是标准的一部分,所以如果有人想知道这不是聚合物的一部分,但他们确实是make a polyfill for it。
其中定制元素类(构造函数)自行注册的元素,就足够了检查类
的存在我不知道如果我的回答适合他的需求更好,但是这是一个有用的附加信息很好的答案。谢谢! – 2015-02-01 15:54:17
我很高兴你找到了有用的答案。 – mudasobwa 2015-02-02 09:50:39
很好的答案。在测试一个元素是否被注册的时候要小心,'document.createElement(name).constructor'部分实际上创建了元素(如果它已经被注册了),并且你会发现你正在搜索你的Polymer元素的准备事件为什么会两次发射:) – 2016-11-26 19:49:31