为什么在 Web 组件中使用时会覆盖而不是调用 setter?

问题描述 投票:0回答:1

我正在尝试学习如何使用 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

javascript html web-component
1个回答
0
投票

Apple/Safari 已经声明,7 年多来,他们永远不会实施 Customized Built-In Elements。所以

extends HTMLTableRowElement
只适用于Chromium和FireFox``

所以它可能是一个扩展

HTMLTableRowElement
在Chromium和FireFox中也有问题。

重写您的代码以仅扩展 HTMLElement

© www.soinside.com 2019 - 2024. All rights reserved.