Когда мы настраиваем встроенные обработчики щелчков внутри ванильных веб-компонентов, this
ниже ссылается на элемент h1
.
export default class wc_parent extends HTMLElement {
constructor() {
super()
this.attachShadow({mode: 'open'})
}
render() {
const template = document.createElement('template')
template.innerHTML = `
<h1 onclick="this.handle_click(event)">hello</h1>
<style>
:host {
display: block;
}
</style>
`
this.shadowRoot.appendChild(
template.content.cloneNode(true)
)
}
handle_click(e) {
console.log(e)
}
connectedCallback() {
this.render()
}
}
Если мы хотим обрабатывать щелчок в режиме inline, нам нужно сделать так, чтобы он работал вот так, внутри connectedCallback()
:
connectedCallback() {
this.shadowRoot.addEventListener('click', this.handle_click)
}
Жизнь станет немного проще, если мы сможем сделать так, чтобы this
внутри onclick="this.handle_click(event)"
указывал на компонент вместо объекта window
, как в React. Я думал добавить свойство окна и указать на этот компонент window[this.localName] = this
, а затем заменить this
на window[this.localName]
внутри метода render()
.
export default class wc_parent extends HTMLElement {
constructor() {
super()
this.attachShadow({mode: 'open'})
window[this.localName] = this
}
render() {
const template = document.createElement('template')
template.innerHTML = `
<h1 onclick="this.handle_click(event)">hello</h1>
<style>
:host {
display: block;
}
</style>
`
// replace this to window['wc-parent']
template.innerHTML = template.innerHTML.replace(
/this/g,
`window['${this.localName}']`
)
this.shadowRoot.appendChild(
template.content.cloneNode(true)
)
}
handle_click(e) {
console.log(e)
}
connectedCallback() {
this.render()
}
}
Вот как это отображается в front end, если мы проверим элементы HTML. Эта часть onclick="window['wc-parent'].handle_click(event)"
имеет смысл, так как она ясно указывает на то, что мы можем найти этот метод внутри компонента wc-parent
.
<wc-parent>
#shadow-root (open)
<h1 onclick="window['wc-parent'].handle_click(event)">hello</h1>
</wc-parent>