ExecCommand ()现在已经过时了,还有其他选择吗?

我打算使用 Document.execCommand()方法和 contenteditable属性来构建我的自定义所见即所得编辑器。但是当我检查 文件Document.execCommand()时,我发现它现在已经过时了。现代(或现存)的替代品是什么?

89077 次浏览

我创建 Rich Editor 是为了我的平台的 XML (HTML5 + XHTML)编辑目的。我不会说 document.execCommand()是完全死了,因为它的一些部分仍然工作良好。不幸的是,对我来说最主要的问题是浏览器使用了很多不同的代码来生成这些样式,这些样式被那些盲人或几乎盲人使用的屏幕阅读器所识别。

除此之外,我需要克服的最昂贵的时间错误是 Gecko/Presto 错误,在这个错误中,视觉和技术选择(为什么它们不是一回事,别问我)会导致部分 DOM 被改变,而用户并不打算这样做,这将归结为每个字符的像素数很低,所以如果富编辑器执行 没有的视觉选择,用户会很快离开。这需要 四个月来克服,而且还有其他的错误。

最终,这是一个艰难但可以实现的努力,但如果你打算像我一样构建一个 HTML/XML 编辑器,你应该计划至少六个月,如果你不仅计划正确地完成它,测试它到讨厌蛋糕的地步,然后只有有人来指出另一个错误。

你的 初选焦点 JavaScript 智能应该在以下方面:

不同浏览器使用 execCommand()产生的不一致的代码(经常设置内嵌样式,如果不彻底否定它,会使你的网站的 CSS 复杂化) ,你应该坚持使用下面的元素,你不仅可以控制,虽然与屏幕阅读器兼容:

  • em表示强调(或“斜体”,不推荐使用 <i>)。
  • strong用于强读文本(或“粗体”,不推荐使用 <b>)。
  • u用于下划线(确保锚的样式与 u 元素不同; u 也许吧被认为是“不推荐的”,尽管我会在未来十年左右修改标准时逆转这一点,适当地使用它)。
  • sub表示垂直低于正常文本的子行文本。
  • sup表示垂直高于正常文本的超级行文本。
  • 没有是否使用 <span>元素来专门添加这些样式,因为屏幕阅读器将 没有理解或揭示错误行为; 它仍然是一个有效的通用内联元素 如果使用得当

实际上,我一直打算修改我的 Rich Editor (它已经被修补了,但还没有被正确地重写) ,不过,当源代码加载到我个人资料中链接的网站的博客页面时,欢迎您查看源代码。最初的项目花了我11个月,但以我现在的经验,我认为它会采取我约3至4个月。如果你是认真的,我强烈建议你远离框架和库。“但是... 但是,他们使生活更容易!”直到你想用一个新版本,不得不重写整个项目。第一次使用纯 JavaScript,否定无意义的维护。祝你好运!


2021年09月24日: 大约一年前,我终于恢复了 Rich Editor II 的工作,成功地将样式从100,515个字符转换为6,000个字符,并将文件请求(压缩后的有效带宽)减少了整整三分之一。以下是这一成功的关键部分:

  1. anchorNodefocusNode可以根据您选择从左到右还是从右到左进行切换。因为我找不到任何理由来解释为什么(对我的平台来说)这很重要,所以我把 an对象(对于 anchorNode)放在左边,而 fn对象(对于 focusNode)总是放在右边。

  2. 我使用约1700个字符解决了 Gecko/Presto 问题; 您可以首先在站点上找到它(访问具有 Rich 表单的页面)。

  3. 为了解决通过 <s><sub><sup><u>等多种交换进行选择的问题(你必须测试简单和复杂的例子) ,我最终使用了 window.getSelection().getRangeAt(0).commonAncestorContainercloneNode,然后在处理 <sub>0之前,去除了选择中没有包含的内容。然后,我简单地使用 window.getSelection().deleteFromDocument();删除选择,并通过 document.createElement用新的样式元素替换它,我可以轻松地 appendChild的选择,并插入到 window.getSelection().getRangeAt(0).insertNode(id_('editor_rich_text').firstChild);

Gecko 浏览器,比如 Waterfox、苍白的月亮(Pale Moon)和现在已经被彻底摧毁的火狐(Firefox) ,允许你选择多个文本实例。要做到这一点,只需按住 Control键,创建额外的选择。因为它没有任何有意义的帮助(这些东西已经够复杂的了) ,所以我没有刻意去支持它。

我将在今天或本周末更新我的平台,以反映新的变化。由于 Gecko 浏览器的许多问题,我保留了很多旧代码。我已经扩展了这个功能,解决了许多 bug,并且不必求助于任何技巧,像往常一样没有车库(框架或库)。


2021年9月26日: 对于那些对重做/撤销功能感兴趣的人来说,你必须基本上保留你正在编辑的 DOM 部分的文本版本。当然,可能还有其他方法来实现它,尽管这些方法会非常复杂。您基本上只需使用 .cloneNode复制编辑器父元素,然后在内存中使用类似于 while (e.firstChild) {xml += new XMLSerializer().serializeToString(e.firstChild);}的内容。因为将它存储为文本,所以它不会像 DOM 那样具有巨大的内存影响。您将逐字地替换编辑器中的整个 DOM,并跟踪变更的每一次迭代,因此它仍然是一个庞大的项目。对于我的平台来说,现在没有必要这么做,尽管有些人已经在评论中提到了,我还是想谈谈这个问题。

看来另一个选择是 输入事件级别2

虽然创建一个自制的所见即所得编辑器非常有吸引力,但我个人将坚持使用 ExecCommand,直到新标准出现。因为我们都只是自己编写一个完整的编辑器,而不是重复使用现有的工作解决方案。

document.execCommand()的替代方案是剪贴板 API,通过 navigator.clipboard.Per MDN Web Docs (https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API) :

这个 API 用于取代使用 document.ExecCommand ()访问剪贴板。

编辑: 正如上面的注释和引用的文本中所提到的,这只能满足需求的一个子集(剪贴板访问)。

参考文件说这是警告。

据预测,在未来这两种规格将被 内容可编辑 输入事件

正如每一个预言一样,只要等待确定。

2022年的答案: execCommand()已经正式过时/废弃,但没有其他选择。因此,如果必须支持富文本,那么必须继续使用 execCommand(),并弄清楚自己希望支持哪些浏览器。

请注意,现实世界中的用户代理(如 Chrome、 Firefox 和 Safari 等浏览器)不能放弃对 execCommand()的支持,因为有太多的服务需要对它的支持。可悲的是,HTML5不能指定任何共同点。这是因为浏览器厂商不同意 execCommand()应该如何工作。因此,HTML5没有什么可以指定的,它的总体目标是指定所有的东西-只有东西-所需要的充分互操作性,任何新的浏览器进入市场。然而,在我看来,HTML5在这里失败了,因为 execCommand()的兼容性实际上是 需要,任何新的浏览器都可以进入市场。因此,将至少一个特定于浏览器的实现标准化为官方实现是有意义的。

当前的所有标准化工作(Input Events 2,Clipboard API)甚至都无法覆盖 execCommand()实际具备的功能(例如,撤消/重做,实际更改选择范围内的内容)。

最难解决的部分是插入符号移动、选择文本、不同的 IME (输入法编辑器)行为和处理本机剪贴板。根据浏览器和操作系统的不同,它们都以不同的方式相互作用。例如,iOS Safari 在 iPad 上编写繁体中文时的行为与在 Windows 上使用泰文 IME 的 Firefox 完全不同。这不同于在 Chromebook 上运行的 Chrome 浏览器,它可以写芬兰语,也可以输入多个 unicoDE 点编码的表情符号。由于没有任何可用的 JS API 披露所有细节,因此对于大多数浏览器来说,您必须使用 contenteditable,可能还要使用 execCommand(),以便从 IME 中获得正确的输入。

还要注意的是,比如 Android GBoard 也需要知道相同可编辑内容中的周围文本,因为它使用 AI 逻辑来正确计算在输入文本时给用户提供哪些单词建议,所以你不能用插入符号下的单个不可见区域来伪造这个建议,因为那样会错过上下文。这并没有阻止人们试图做到这一点,但它在实践中以各种方式失败了。

这种情况已经持续了五年多,所以也不要指望任何快速的变化。

这里的结论是,即使 W3C有一个关于 execCommand()的警告,它仍然可以工作,即使到了2022年也没有标准的替代品,除非使用 javascript 版本库。

你可使用以下连结:

navigator.clipboard.writeText('text to be copied');

document.execCommand("copy");完全一样

可以使用以下方法制作所见即所得编辑器

window.getSelection()

但是现在继续使用 ExecCommand 不是问题。