Как получить список зарегистрированных пользовательских элементов
Я пытаюсь определить, был ли зарегистрирован пользовательский элемент с определенным именем или нет. Есть ли способ сделать такую проверку?
Или есть способ получить список зарегистрированных пользовательских элементов?
Я делаю document.registerElement
, но что еще там? Это односторонний API?
Ответы
Ответ 1
Существует способ проверить, был ли элемент зарегистрирован. У зарегистрированных элементов есть свои собственные конструкторы, в то время как незарегистрированные будут использовать простой 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) лучше подходит для ваших нужд.
Ответ 2
В настоящее время не существует способа увидеть все зарегистрированные элементы, но есть способ проверить, был ли уже зарегистрирован элемент: заверните регистр в блок try...catch
:
try {
document.registerElement('x-my-element');
} catch(e) {
console.log('already exists', e);
}
Запустите это дважды в консоли, и вы увидите сообщение об ошибке.
У этого есть недостаток, если вы просто хотите проверить, зарегистрирован ли он или нет: если бы это было не так, это произойдет после его запуска. Также нет способа отменить регистрацию элемента, который кажется.
Ответ 3
Хотя я не уверен, что это относится к другим структурам веб-компонентов, при использовании Polymer в Chrome у меня есть объект CustomElements
для объекта window
. Объект CustomElements
имеет коллекцию ключей/значений всех зарегистрированных пользовательских элементов, называемых registry
.
function isRegistered(name) {
if (window.CustomElements && window.CustomElements.registry)
return name in window.CustomElements.registry;
return undefined;
}
Ответ 4
Объединяя несколько из приведенных выше подходов, вы можете перебирать все используемое и выплевывать уникальный список пользовательских (и зарегистрированных) элементов:
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))
![введите описание изображения здесь]()
Ответ 5
Поскольку пользовательские элементы теперь являются частью последнего стандарта, я думал, что поделился бы тем, как это сделать в 2017 году +:
Примечание: функция document.registerElement
была устарела в пользу customElements.define().
customElements
определяется как глобальное значение в window
. Существует три метода:
get
является важным здесь. get
принимает string
имени элемента и возвращает конструктор для именованного настраиваемого элемента или undefined
, если для имени нет определенного определения элемента.
Итак, в 2017 году, чтобы проверить, зарегистрирован ли элемент, вы:
const myElementExists = !!customElements.get('my-element');
Я не уверен, есть ли способ получить список определенных элементов. Важно также отметить, что хром является единственным браузером, который определяет это изначально в этот момент времени. CustomElements v1 являются частью стандарта, поэтому это не является частью Polymer, если кто-то задавался вопросом, но они сделали сделать polyfill для него.
Ответ 6
Как уже написано на канале Polymer Slack, это грязный, который может сделать работу:
function isElementRegistered(elementId) {
return Polymer.telemetry.registrations.find(function(item) { return item.is === elementId })
}
Не уверен, насколько Polumer.telemetry.registrations
является надежным, хотя (не видел его в документе), а Array.prototype.find
не является кросс-браузером!
Ответ 7
в сценариях, где пользовательские классы элементов (конструкторы) самостоятельно регистрируют элемент, достаточно проверить наличие класса