一応 Part にアクセスすれば RenderOptions の値を options プロパティで持ってるのでアクセスできるといえばできるのですが Part は公開されていないため __part に無理やりアクセスするような方法になります
minify で名前が変わるかもしれませんし あまりアクセスしたいところではないです
自分で持たせようにも Directive のインスタンスを作る処理に手を加えることはできないです
render の処理の中で directive の関数を呼び出すときに都度 this を渡せば Directive の render メソッドの引数として渡せますが 全てにそれを書くのは避けたいです
render() {
return html`<div>${directive1(this, foo, bar)}</div>`
}
自動で this を追加で渡すようにラップした関数をプロパティで持たせておくこともできます
constructor でこういう感じのことをします
this.directive1 = (...args) => directive1(this, ...args)
これだと Directive の render メソッドの第一引数で host を受け取ることになります
Directive のインスタンスのプロパティに入ってるほうが自然な気がするので directive 関数を呼び出して directive の関数を作るところでクラスも作ります
インスタンスごとに異なるクラスになります
このクラスを作るときにスコープ的にホストのカスタム要素を見れるようにして これを参照させます
コードにするとこんな感じになりました
import { html, LitElement } from "lit"
import { directive, Directive } from "lit/directive.js"
const customElementDirective = (element, Directive) => {
return directive(
class extends Directive {
host = element
}
)
}
class Dire extends Directive {
host = null
constructor() {
super()
console.log("Directive created")
}
render(name) {
console.log("Directive rendered", this.host, name)
return "a"
}
}
class ExampleElement1 extends LitElement {
d = customElementDirective(this, Dire)
render() {
return html`
<div class=${this.d("A")}>${this.d("B")}</div>
`
}
}
class ExampleElement2 extends LitElement {
static properties = {
n: {}
}
constructor() {
super()
this.d = customElementDirective(this, Dire)
this.n = 0
}
render() {
return html`
<button @click=${() => this.n++}>${this.n}</button>
<div>${this.d("A")}</div>
${this.n % 2 === 0
? html`<div class=${this.d("B")}>${this.d("C")}</div>`
: null
}
`
}
}
customElements.define("example-element1", ExampleElement1)
customElements.define("example-element2", ExampleElement2)
example-element1 と example-element2 が使用例です
2 の方では ボタンを押すとプロパティを更新して表示内容を切り替えています
下の div の表示の有無が切り替わります
一旦消えてから DOM が再作成されるときに Directive のインスタンスも作り直されます
これを使えば画面の更新時にホストの要素も更新する Directive が作れそうです