我正在尝试学习如何使用 Web 组件制作自定义表格,并且我正在尝试使用 getter 和 setter 在我的自定义元素上定义属性。这是一个非常简单的表,只有一列,以及一个具有
line_number
属性的自定义行元素。创建一个自定义表,然后设置 line_number
按预期工作,调用 setter 并将值放入适当的元素中。但是,如果 line_number
是由自定义表的构造函数设置的,如下面的 serial-log-setter-broken
所示,setter 不会被调用并且似乎已被删除(稍后尝试调用它没有任何作用)。
customElements.define('serial-log-setter-broken', class extends HTMLElement {
constructor() {
super()
this.attachShadow({
mode: 'open'
}).innerHTML = `
<table>
<thead>
<tr>
<th>Line Number</th>
</tr>
</thead>
<tbody></tbody>
</table>`
this.rows = []
for (let i = 0; i < 4; ++i) {
this.rows[i] = document.createElement('tr', {
is: 'serial-log-entry'
})
// .line_number's setter isn't called here, and seems to be deleted instead
this.rows[i].line_number = i + 1
this.shadowRoot.querySelector('tbody').appendChild(this.rows[i])
}
}
})
customElements.define('serial-log-setter-working', class extends HTMLElement {
constructor() {
super()
this.attachShadow({
mode: 'open'
}).innerHTML = `
<table>
<thead>
<tr>
<th>Line Number</th>
</tr>
</thead>
<tbody></tbody>
</table>`
this.rows = []
for (let i = 0; i < 4; ++i) {
this.rows[i] = document.createElement('tr', {
is: 'serial-log-entry'
})
this.shadowRoot.querySelector('tbody').appendChild(this.rows[i])
}
}
})
customElements.define('serial-log-entry', class extends HTMLTableRowElement {
constructor() {
super()
this.innerHTML = '<td>1</td>'
this._line_number_cell = this.querySelector('td')
}
get line_number() {
return Number(this._line_number_cell.textContent)
}
set line_number(v) {
console.log('Setter called')
this._line_number_cell.textContent = Number(v)
}
}, {
extends: 'tr'
})
console.log('This will print nothing')
document.getElementsByTagName('serial-log-setter-broken')[0].rows.forEach((v, i) => {
v.line_number = i + 1
})
console.log('This will print "Setter called" 4 times')
document.getElementsByTagName('serial-log-setter-working')[0].rows.forEach((v, i) => {
v.line_number = i + 1
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Setter overwritten</title>
</head>
<body>
<serial-log-setter-broken></serial-log-setter-broken>
<serial-log-setter-working></serial-log-setter-working>
</body>
</html>
为什么 setter 在 Web 组件外部使用时有效,但在其内部使用时被删除?
注:
serial-log-setter-broken
和serial-log-setter-working
几乎相同,区别在于是否使用line_number
setter
Apple/Safari 已经声明,7 年多来,他们永远不会实施 Customized Built-In Elements。所以
extends HTMLTableRowElement
只适用于Chromium和FireFox``
所以它可能是一个扩展
HTMLTableRowElement
在Chromium和FireFox中也有问题。
重写您的代码以仅扩展 HTMLElement