web-dev-qa-db-ja.com

登録されたカスタム要素のリストを取得する方法

特定の名前のカスタム要素が登録されているかどうかを検出しようとしています。そのようなチェックを行う方法はありますか?

または、登録されたカスタム要素のリストを取得する方法はありますか?

私がやります document.registerElement、しかし他に何がありますか?一方向のAPIですか?

39
dy_

要素が登録されているかどうかを確認する方法があります。登録された要素には独自のコンストラクターがありますが、登録されていないものはコンストラクターにプレーン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にアクセスする方法はありません。

ところで、私はtry-catched登録(@ stephan-mullerが提案)があなたのニーズにより適しているとまだ思います。

48

上記のアプローチのいくつかを組み合わせると、使用中のすべてを反復して、カスタム(および登録済み)要素の一意のリストを吐き出すことができます。

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

26
Paul Irish

カスタム要素が 最新の標準 の一部になっているので、2017 +でこれを行う方法を共有すると思いました:

注:document.registerElement関数が追加されました customElements.define()。の採用により非推奨

customElementswindowでグローバルとして定義されています。 つのメソッドが定義されています

  1. define
  2. get
  3. whenDefined

ここではgetが重要です。 getは要素名のstringを取り、名前付きカスタム要素のコンストラクターを返します。名前にカスタム要素定義がない場合はundefinedを返します。

2017年以降、要素が登録されているかどうかを確認するには:

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

しかし、定義された要素のリストを取得する方法があるかどうかはわかりません。


注:これはIEでは機能しません。 ブラウザの互換性についてはこちらをご覧ください

25
Rico Kahler

現在、登録されているすべての要素を確認する方法はないようですが、要素がすでに登録されているかどうかを確認する方法があります。レジスタをtry...catchブロックでラップします。

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

コンソールでこれを2回実行すると、ログに記録されたエラーが表示されます。

ただし、登録されているかどうかを確認したいだけの場合は欠点があります。登録されていない場合は、これを実行した後になります。要素の登録を解除する方法もありません。

9
Stephan Muller

他のWebコンポーネントフレームワークに適用されるかどうかはわかりませんが、ChromeでPolymerを使用している場合、CustomElementsオブジェクトからwindowオブジェクトへのオブジェクトがあります。CustomElementsオブジェクトには、登録されているすべてのキー/値のコレクションがあります。 registryと呼ばれるカスタム要素。

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

PolymerのSlackチャネルで既に書かれているように、これは仕事をすることができる汚いものです:

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

どれくらいかわからないPolumer.telemetry.registrationsは信頼できますが(ドキュメントでは見ていません)、Array.prototype.findはクロスブラウザではありません!

3
lzzluca

カスタム要素クラス(コンストラクタ)が要素を自己登録するシナリオでは、クラスの存在を確認するだけで十分です

1
Markus