【发布时间】:2021-12-19 18:05:48
【问题描述】:
让我们有内容可编辑的 div。浏览器本身管理它的撤消。 但是,当脚本(除了用户操作之外)进行其他内容更改(或触摸选择范围)时,它会停止按用户预期运行。
换句话说,当用户按下 Ctrl+Z 时,div 内容不会恢复到之前的状态。
看下面的简化仿真例子:
https://codepen.io/farin/pen/WNEMVEB
const editor = document.getElementById("editor")
editor.addEventListener("keydown", ev => {
if (ev.key === 'a') {
const sel = window.getSelection()
const range = window.getSelection().getRangeAt(0)
const node = range.startContainer;
const value = node.nodeValue
node.nodeValue = value + 'aa'
range.setStart(node, value.length + 2)
range.setEnd(node, value.length + 2)
ev.preventDefault()
}
})
所有书写的“a”字母都翻倍。
只要没有输入“a”,就可以撤消。 当用户键入“a”(作为双 'aa' 附加到文本中)并按 Ctrl+Z 时,他预计两个 'a' 都将被删除并且光标会移回原始位置。
取而代之的是,撤消时只恢复一个“a”,而脚本添加的第二个保留。
如果事件也被 preventDefault() 阻止(在本示例中不需要,但在我的真实示例中我几乎无法避免它),那么一切都会变得更糟。 因为撤消会还原以前的用户操作。
我可以想象整个撤消/重做的东西将由脚本管理,但这意味着实现整个撤消/重做逻辑。这太复杂了,可能很脆弱,而且可能有很多故障。
相反,我想告诉浏览器存在原子更改,应该由一个用户撤消还原。这可能吗?
【问题讨论】:
-
这并不能直接回答您的问题,但是根据我的经验,尝试使用原始内容可编辑 div 构建强大的用户体验是一个问题的兔子洞——您遇到了其中一个问题,但是你可能还不知道还有几十个。我建议放弃并使用像
quill或draft.js这样的库。 -
@AndrewStegmaier 我目前正在使用羽毛笔。我的情况不需要工具栏。只有自定义操作存在,作为 quill 插件实现。它面临着 quill 的一些限制,我考虑使用纯内容可编辑 div。我有概念证明,直接执行操作效果更好,唯一的问题是撤消/重做。 (我的用例类似于在 facebook 或 twiitter 上发布 creatin,很少有丰富的内容(fb 有提及,twitter 有链接)
-
@AndrewStegmaier 换句话说,我永远不想构建自己的全功能编辑器。但在这种特定情况下,我不确定。使用 quill,我面临一些恼人的故障和 api 限制(比如我可以事后更新内容,wchich 会为用户带来明显的延迟)
-
@AndrewStegmaier 你是对的 :) 但在我看来,正确的解决方案似乎是 TipTap。真的很喜欢它的多功能和简单的界面。所以最终它变成了从 Quill 到 TipTap 的迁移。它解决了我使用 Quill 的问题,并通过可编辑的纯内容避免了地狱。
标签: html editor contenteditable undo