我正在try 学习如何使用Web组件创建自定义表,并try 使用getter和setter在我的自定义元素上定义属性.下面是一个非常简单的表,其中有一列,以及一个具有line_number属性的定制行元素.通过调用setter并将值放入适当的元素中,创建自定义表,然后设置line_number就可以正常工作.但是,如果定制表的构造函数设置了line_number,如下面的serial-log-setter-broken中所示,则不会调用该设置器,并且看起来已被删除(稍后try 调用它不会产生任何效果).

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组件外部使用时可以工作,但在Web组件内部使用时会被删除?

注:serial-log-setter-brokenserial-log-setter-working几乎相同,但在是否使用line_number定位器方面有所不同.

推荐答案

这是关于定义的顺序.

在定义serial-log-entry之前定义并执行serial-log-setter-broken.您可以通过将日志(log)消息添加到serial-log-setter-broken元素的构造函数来判断这一点.日志(log)消息在"This‘ll Print Nothing"消息之前打印.

这是一种奇怪的行为.我自己也没有意识到这一点.

当你把serial-log-entry的定义移到serial-log-setter-broken的定义之上时,它就起作用了.

注意,您可能会重新考虑扩展内置元素,因为Safari(新的IE)拒绝支持"is"属性.请参见herehere.

Javascript相关问答推荐

jest使用useLocate测试自定义挂钩

在贝塞尔曲线的直线上找不到交叉点:(使用@Pomax的bezier.js)

如何在RTK上设置轮询,每24小时

浮动Div的淡出模糊效果

如何将Map字符串,布尔值转换为{key:string;value:bo布尔值;}[]?<>

如何让npx在windows中运行js脚本?

手机上的渲染错误文本必须在文本组件中渲染,但在浏览器上没有问题<><>

JS,当你点击卡片下方的绿色空间,而它是在它的背后转动时,

在WordPress中使用带有WPCode的Java代码片段时出现意外令牌错误

覆盖TypeScrip中的Lit-Element子类的属性类型

Eval vs函数()返回语义

本地库中的chartjs-4.4.2和chartjs-plugin-注解

如何在Angular拖放组件中同步数组?

如何在我的Next.js项目中.blob()我的图像文件?

Vaadin定制组件-保持对javascrip变量的访问

当我try 将值更改为True时,按钮不会锁定

将对象推送到数组会导致复制

WebSocketException:远程方在未完成关闭握手的情况下关闭了WebSocket连接.&#三十九岁;

MongoDB中的嵌套搜索

Jexl to LowerCase()和Replace()