Svelte contenteditable 未正确更新

Svelte contenteditable is not updated properly

我用 Svelte 创建了电子表格,但它似乎无法正确更新单元格。

我将“2”后缀附加到每个单元格,当我编辑内容时(比如将 jim 中的第一个字母固定为大写),它应该以两个“2”作为“Jim22”结尾。但它最终只有一个“2”作为“Jim2”。

我也有 JSON 输出来检查 rows 的值,它发生了变化,因此组件已正确更新,但可编辑单元格未更新为“Jim22”,它仍然“吉姆2".

为什么,以及如何解决这个问题?

playground

代码

<script>
  let rows = [
    ["jim"],
    ["Kate"]
  ]

  function update(i, j, event) {
        rows[i][j] = event.target.innerText
  }
</script>

<table>
  {#each rows as row, i}
    <tr>
      {#each row as cell, j}
        <td contenteditable="true" on:blur="{(event) => update(i, j, event)}">{cell}2</td>
      {/each}
    </tr>
  {/each}
</table>

<pre>{JSON.stringify(rows, null, 2)}</pre>

只需为每条语句添加键即可。根据 document

<script>
  let rows = [
    ["Jim",  "Raynor"],
    ["Kate", "Bishop"]
  ]

  function update(i, j, event) {
        rows[i][j] = event.target.innerText
  }
</script>

<table>
  {#each rows as row, i (row)}
    <tr>
      {#each row as cell, j (cell)}
        <td contenteditable="true" on:blur="{(event) => update(i, j, event)}">{cell}2</td>
      {/each}
    </tr>
  {/each}
</table>

<pre>{JSON.stringify(rows, null, 2)}</pre>

我不认为Long Vu的回答是问题的根本原因,因为它无法解释为什么问题评论中提到的修改有效。添加键是一种解决方法。

经过一些调试和搜索,我发现了这个问题:Repeat words in plain text aren't reactive. When trying to update "Jim" to "Jim2", svelte uses set_data function,比较text.wholeText === datatext.data"Jim"text.wholeTextdata 都是 "Jim2",所以跳过更新。

About wholeText:

The Text.wholeText read-only property returns the full text of all Text nodes logically adjacent to the node.

因此,通过检查 tdchildNodes 属性:

  • <td>{cell}2</td>有两个Text节点:"Jim""2",而wholeText"Jim2"
  • <td>{cell + "2"}</td>有一个Text节点,没问题
  • <td>{@html cell}2</td> 没有使用 set_data 功能,没问题

同样如问题所述,将 svelte 降级到 v3.23.2 会使 <td>{cell}2</td> 按预期工作。