【问题标题】:execCommand() is now obsolete, what's the alternative?execCommand() 现在已经过时了,有什么替代方案?
【发布时间】:2020-06-20 04:56:01
【问题描述】:

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

【问题讨论】:

  • 看看这个:MDN: Making content editable - 虽然它似乎也引用了document.execCommand()...
  • 还有一个事实是contenteditable 是一个非常不可预测的野兽,所以你可能想考虑甚至不使用contenteditable,而是将元素换成一个预先加载了该元素内容的编辑器在。
  • 几乎没有,使用 vue 和 react 等。如今,编写一些将用户点击的元素替换代码文本区域(纯文本区域, Draftail、CodeMirror 等),以便可以对其进行编辑,然后在模糊时用更新的内容反向替换原始元素。哎呀,你甚至不需要一个框架,元素交换代码很容易用 vanilla JS 编写,并且将提供比contenteditable 所能提供的更多的控制。

标签: javascript html css execcommand


【解决方案1】:

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

此外,我必须克服的最昂贵的时间错误是 Gecko/Presto 错误,其中视觉和技术选择(为什么它们不是同一件事,别问我)会导致 DOM 的一部分被改变了用户不打算这样做,这将归结为每个字符的像素数很低,因此如果富编辑器尊重视觉选择,用户会很快走开。这需要 四个月 才能克服,而且还有其他错误。

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

您的 主要 JavaScript 重点应该放在以下方面:

代替使用来自不同浏览器的execCommand() 生成的不一致代码(通常设置内联样式,如果不完全否定它会使您网站的 CSS 复杂化),您应该坚持使用以下元素,您不仅可以控制这些元素虽然与屏幕阅读器兼容:

  • em 表示强调(或“斜体”,<i> 已弃用)。
  • strong 用于强读文本(或“粗体”,<b> 已弃用)。
  • u 用于下划线(确保您的锚点的样式与 u 元素区分开来;u 可能被视为“已弃用”,尽管我会在未来十年或所以,适当地使用它)。
  • sub 用于显示垂直低于正常文本的子行文本。
  • sup 用于垂直显示高于普通文本的超行文本。
  • 不要使用<span>元素来专门添加这些样式,因为屏幕阅读器将理解或揭示错误行为; 如果使用得当,它仍然是一个有效的通用内联元素。

实际上,我一直打算修改我的富编辑器(虽然尚未正确重写,但它已得到修补),尽管欢迎您在我的个人资料中链接的网站的博客页面上加载源代码时查看它。最初的项目花了我 11 个月,但根据我现在的经验,我认为我需要大约三到四个月。如果您是认真的,我强烈建议您远离框架和库。 “但是……但是,它们让生活更轻松!” ...直到您想使用新版本并且必须重写整个项目。第一次使用纯 JavaScript 并否定无意义的维护。祝你好运!


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

  1. anchorNodefocusNode 可以根据您选择从左到右还是从右到左切换。因为我找不到任何理由说明为什么这很重要(对于我的平台),所以我在左侧创建了 an 对象(对于 anchorNode),并且始终在右侧创建了 fn 对象(对于 focusNode)一边。

  2. 我使用约 1,700 个字符解决了 Gecko/Presto 问题;您可以先在网站上找到它(访问具有丰富表单的页面)。

  3. 为了解决<s><sub><sup><u> 等通过大量交换选择的问题(您必须测试简单和非常复杂的示例)我最终使用window.getSelection().getRangeAt(0).commonAncestorContainer 和@987654362 @ 然后在处理之前 that 剥离了选择中未包含的内容。然后我简单地使用window.getSelection().deleteFromDocument(); 删除选择并通过document.createElement 将其替换为新样式元素,我可以轻松地将选择appendChild 插入到window.getSelection().getRangeAt(0).insertNode(id_('editor_rich_text').firstChild);

Gecko 浏览器(例如 Waterfox、Pale Moon 和现已完全销毁的 Firefox)允许您选择多个文本实例。为此,只需按住Control 键即可创建额外的选择。由于它并没有以任何有意义的方式真正提供帮助(而且这些东西已经足够令人费解了),所以我现在没有竭尽全力支持它。

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


2021-09-26:对于那些对重做/撤消功能感兴趣的人,您将不得不求助于基本上保留您正在编辑的 DOM 部分的文本版本。当然,可能还有其他方法来实现它,尽管这些方法会非常复杂。您基本上只需使用.cloneNode 复制编辑器父元素,然后在内存中使用类似于while (e.firstChild) {xml += new XMLSerializer().serializeToString(e.firstChild);} 的内容。由于您将其存储为文本,因此不会像 DOM 那样具有巨大的内存影响。您实际上将在编辑器中替换整个 DOM 并跟踪更改的每次迭代,因此它仍然是一个庞大的项目。对于我的平台,现在没有必要,虽然我想介绍这一点,因为有些人在 cmets 中提到了它。

【讨论】:

  • 所以基本上我应该得到当前的选择并确定我是否需要用例如包围它一个span-标签(例如设置font-weighttext-decoration)或例如分割跨度(通过确定任何交叉点并可能关闭甚至删除它们),对吗?另一种解决方案可能是将每个字母包装在span-tag 中,但我怀疑随之而来的是可怕的性能开销 - 特别是在较大的文本上......
  • @Igor 虽然没有,但我已经更新了我的答案,not 使用span 元素来实现样式。如果您需要强烈地表达句子的一部分,您应该在示例中使用<strong>,以便屏幕阅读器能够理解并强烈地为盲人和视力障碍者复读. <span> 元素在使用得当时仍然占有一席之地,并且还有其他类型的元素。就性能而言,真正的问题是处理高度嵌套的“样式”(从<em><strong><u>example</u></strong></em> 的中间或侧面添加或删除u)或处理双重嵌套。
  • 啊-谢谢!所以我应该更喜欢ustrong等最精确的文本而不是span?我的意思是 .. 像 JAWS 这样的屏幕阅读器确实会根据我在开发应用程序时所记得的 aria-attributes 来解释,这些程序也必须能够被此类程序读取。是的..嵌套是真正的麻烦所在..所以我想我也不应该使用contentEditable
  • @Igor 我的网络平台仍然使用原始的富编辑器(您可以通过 cmets 在博客线程页面上进行预览,除非需要,否则不会加载,按需 JavaScript)。 contentEditable 属性有效。至于处理复杂的嵌套,有两件事要做:1. 为最大复杂性设置策略,并在超过时指示用户使用 XML 编辑器;以及 2. 确定最大阈值以使您的项目发布变得现实。如果您决定对复杂性进行疯狂模仿,请模仿 LibreOffice 的行为;我认为它目前是处理这种复杂性的“标准”。
  • @ChuanqiSun 我目前最好的想法是使用 data-edit 或类似的非侵入性 HTML/XML 属性跟踪更改,并根据它在已编辑内容中的相对位置分配一个值和/或者之前的元素是什么。撤消/重做是一种有序执行,因此您只需在JavaScript/CSS 属性选择器上向前或向后迭代。由于我正在慢慢重写我的富编辑器,所以我还没有达到这一点。不过,我确定您可能会看到大约 800-1,600 字节的 JavaScript 如果执行得当。
【解决方案2】:

看起来替代方案将是 Input Events Level 2.

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

【讨论】:

    【解决方案3】:

    document.execCommand() 的替代方案是剪贴板 API,通过 navigator.clipboard。每个 MDN 网络文档 (https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API):

    此 API 旨在取代使用 document.execCommand() 访问剪贴板。

    编辑:正如评论中提到的以及上面引用的文本,这仅满足要求的子集(剪贴板访问)。

    【讨论】:

    • 如何使用剪贴板 API 加粗文本、撤消/重做更改等?这只完成了 execCommand 所做的非常有限的子集。
    【解决方案4】:

    reference documentation 表示警告。

    预计未来两种规格都将被替换为 Content EditableInput Events

    正如每一个预测一样,请等待确定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-30
      • 1970-01-01
      • 2020-06-25
      • 2016-08-16
      • 2023-03-13
      • 2022-10-05
      • 2022-06-10
      相关资源
      最近更新 更多