Svelte contenteditable 未正确更新
Svelte contenteditable is not updated properly
我用 Svelte 创建了电子表格,但它似乎无法正确更新单元格。
我将“2”后缀附加到每个单元格,当我编辑内容时(比如将 jim 中的第一个字母固定为大写),它应该以两个“2”作为“Jim22”结尾。但它最终只有一个“2”作为“Jim2”。
我也有 JSON 输出来检查 rows
的值,它发生了变化,因此组件已正确更新,但可编辑单元格未更新为“Jim22”,它仍然“吉姆2".
为什么,以及如何解决这个问题?
代码
<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 === data
。 text.data
是 "Jim"
,text.wholeText
和 data
都是 "Jim2"
,所以跳过更新。
The Text.wholeText
read-only property returns the full text of all Text
nodes logically adjacent to the node.
因此,通过检查 td
的 childNodes
属性:
<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>
按预期工作。
我用 Svelte 创建了电子表格,但它似乎无法正确更新单元格。
我将“2”后缀附加到每个单元格,当我编辑内容时(比如将 jim 中的第一个字母固定为大写),它应该以两个“2”作为“Jim22”结尾。但它最终只有一个“2”作为“Jim2”。
我也有 JSON 输出来检查 rows
的值,它发生了变化,因此组件已正确更新,但可编辑单元格未更新为“Jim22”,它仍然“吉姆2".
为什么,以及如何解决这个问题?
代码
<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 === data
。 text.data
是 "Jim"
,text.wholeText
和 data
都是 "Jim2"
,所以跳过更新。
The
Text.wholeText
read-only property returns the full text of allText
nodes logically adjacent to the node.
因此,通过检查 td
的 childNodes
属性:
<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>
按预期工作。