Web Componentsをちょっと便利にするbenry関数の紹介です。
Web Componentsといえば、カスタム要素のクラスを作ることが主な作業になりますが
その一連の定形作業を自動化するのが目的の関数です。
- ShadowDOMの自動作成
- HTMLの自動挿入
- DOMの自動選択
- イベントの自動登録
benry関数の機能
HTMLをShadowDOMに登録する
-
this.html
にHTML文字列かDOM要素をセットしておくと、自動的にShadowDOMに登録します - CSSも
this.html
内に記述します
DOMの自動選択
- idを持つタグには
this.$id名
でアクセスできます - shadowRootは
this.$shadow
、ホスト要素はthis.$host
に予約されてます
イベントの自動登録
- クラスに
$id名_イベント名
という名前のメソッドがあると、イベントとして登録されます - イベント内の
this
は、クラスのthis
と同じになります (通常はイベントを登録した要素)
benry関数の使用例
benry関数は、クラスのconstructor()
かconnectedCallback()
で使用します。
引数は常にthis
を渡して下さい。
使用例
class MyAppElement extends HTMLElement{
connectedCallback(){
benry(this) // benry関数の実行。shadowDOMが作成され、HTML・イベントが登録される
this.$p.textContent += ' Good-By' // id付きタグに簡単アクセス
}
$p_click(event){ // 登録したいイベント
alert(this.$p.textContent) // イベント内でもクラスのthis
} // イベントの解除は → this.$p.removeEventListener('click', this.$p_click)
get html(){ // 登録したいHTML・CSS
return `
<p id="p">Hello</p>
<style>#p{color:red;}</style>
`
}
}
customElements.define('my-app', MyAppElement) // <my-app></my-app> タグが使えるようになる
- この使用例が覚えることの全てです。簡単
- 操作したいタグには、あらかじめidを付けておくのがコツです。
benry関数のソースコード
ソースは関数が1つだけです。ご自由にお使いください
function benry(self){ // https://qiita.com/economist/items/6c923c255f6b4b7bbf84
self.$host = self
self.$shadow = self.attachShadow({mode:'open'})
if(self.html instanceof Node){
self.$shadow.append(self.html)
}
else{
self.$shadow.innerHTML = self.html ?? ''
}
for(const el of self.$shadow.querySelectorAll('[id]')){
self[`$${el.id}`] = el
}
const methods = Object.getOwnPropertyNames(self.constructor.prototype).filter(v => typeof self[v] === 'function')
for(const method of methods){
self[method] = self[method].bind(self)
const match = method.match(/^(\$.*?)_([^_]+)$/)
if(match){
self[match[1]]?.addEventListener(match[2], self[method])
}
}
}
課題
- addEventListener()の第三引数にどう対応するか? clickOcneCapture みたいな形かな?
- id選択を動的に行うには? https://qiita.com/_likr/items/5519be81af5343cb98e5