【问题标题】:Editable HTML content is very laggy when it is large可编辑的 HTML 内容很大时非常滞后
【发布时间】:2014-07-22 13:03:04
【问题描述】:

例如,我有以下简单的 HTML 页面,其中 <span>[SOME FIELD]</span> 重复多次以弥补大约 200K 的文件大小:

<!DOCTYPE html>
<html>
<head>
</head>
<body editableContent="true">
        <span>[SOME FIELD]</span>
        <span>[SOME FIELD]</span>
...
        <span>[SOME FIELD]</span>
</body>
</html>

随着内容的增长,编辑体验变得非常滞后。输入或编辑内容实际上是不可能的。

这是 complete repro case。要明白我的意思,只需将光标移动到可编辑内容的末尾并尝试编辑。 在 IE 和 Chrome 下会滞后很多时间,几乎无法打字。 不过,它在 Firefox 下运行良好

问题:我需要让它在 IE 下运行得相当快。

到目前为止,我已经接近 IE8 仿真(使用 &lt;meta http-equiv="X-UA-Compatible" content="IE=8"&gt;),所以 this 工作(在 IE 下)。

不过,我也需要支持IE=edge。任何有关如何实现这一点的建议将不胜感激。 IMO,这是一个错误(我提交了 here for IEhere for Chrome),但我正在寻找任何解决方法。

更新,对于在独立 IE 浏览器或托管 WebBrowser control 的自定义应用程序中加载时使用 IE=edge HTML 文档模式的任何解决方案,我们都会提供奖励。

更新,对应的IE bug reported刚刚被关闭为“不会修复”。

【问题讨论】:

  • 如果是简单的内容,你认为你可以为你的可编辑内容使用一个伪装的多行文本框,并在blur上通过javascript添加标记吗?
  • 看起来这个 used 在 Firefox 中也是一个问题...bugzilla.mozilla.org/show_bug.cgi?id=635618
  • 这是很难做到的事情之一(对于浏览器供应商)。 “未来”可能会有所改善。有关为什么这很困难的更多信息:medium.com/medium-eng/…
  • @Noseratio 选择一个字符然后删除它会使IE中的编辑速度恢复正常。也许您可以尝试以编程方式执行此操作?
  • @Temu,你不需要实际实现它,我已经做到了,它可以工作。只需发布您的评论作为答案。干杯。

标签: javascript html internet-explorer webbrowser-control contenteditable


【解决方案1】:

为什么不分解数据并将其存储在数组或 Json 对象中,一次只读取一部分,随着用户滚动或移动内容而更新。这样,在任何时间点都只会处理一小部分。如果您使用 Jquery,您可以从类引用中获取 id。如果您不想使用 Jquery,您可以在原始 Javascript 中编写一个类标识符函数。以下是粗略的,但您可以理解。

<!DOCTYPE html>
<html>
<head>
</head>
<body editableContent="true">
    <span id="item1" class="handle_items">[SOME FIELD]</span>
    <span id="item2" class="handle_items">[SOME FIELD]</span>
    ...
    <span id="item-n" class="handle_items">[SOME FIELD]</span>
</body>
</html>

<script>
$(function(){

    var arrayData = [];

    $(".handle_items").mouseover(function() {
        var identVar = $( this ).prop('id');
        fillHtml(identVar);
    });

    function fillHtml(identVar) {
        $("#" + identVar).html(arrayData[i]);
    }
});
</script>

【讨论】:

  • 对这个问题有类似的评论,所以我会复制我的回复:我看不出 AJAX/分页对可编辑内容有何帮助。实际上,它是一个类似于 Word 的全功能编辑器。例如,它有一个上下文拼写检查器,它取决于光标周围的单词。或者用户如何浏览和选择跨越多个页面的文本块。还是谢谢!
  • 我的示例是 innerHtml 分页,但同样的技术也可以用于将数据写入数组。因此将其分解成更小的部分,并且只处理用户可见的数据。我一直使用这种技术来提高性能。如果您的内容跨越多个页面,我认为在记录数据位置的同时组织 JSON 格式并根据需要组装内容会起作用。我经常将位置数据存储在 id 中,并使用该信息来确定如何处理数据。无论如何,sry它没有帮助。 :-( 总帐
  • 我理解这个概念,但我不确定它是否可以用来实现类似于我的native example 的无缝用户编辑体验(即多行文本流选择、撤消/重做,滚动等)但没有滞后。如果您可以发布一个实际以这种方式工作的概念验证代码,我很乐意再奖励它 500 个。同时,我选择的解决方法是 this
【解决方案2】:

用鼠标或SHIFT + ARROW选择一个字符,然后按DELETE删除,IE中的编辑速度将恢复正常。

【讨论】:

  • 这个答案得到了赏金。我非常乐意为更优雅的解决方案(分页等)提供另一个赏金,该解决方案将实际工作并提供类似于原生编辑的无缝编辑体验。
  • @Noseratio 我已经删除了不适合你的代码。我有一个简化的测试用例,它似乎在其中运行良好。
  • 只是给其他人的注释,只需选择一个字符然后模拟 Home 或箭头键击也可以消除缓慢。
【解决方案3】:

一种解决方案是不将contenteditable = true 用于整个区域(在您的情况下为正文部分)。您可以确定 body 的可见区域,为相应区域创建一个“Range”,并使用contenteditable = true 将其临时包裹在一个元素中。

但是,根据更详细的要求,这种方法可能不适合。 例如,我想到的一个问题是在仅滚动几行后尝试保持插入符号的位置。

【讨论】:

  • 我们实际上已经考虑过这一点,但主要问题是横截面选择,当您想从一个可编辑的 div 开始选择,并在另一个可编辑的 div 中结束时。除了跨可编辑 div 的常规箭头键导航问题之外。还是谢谢!
【解决方案4】:

经过大量的盲目拍摄,我想我找到了一些可能真正有用的东西:

  1. 将一大段 HTML 复制到剪贴板中
  2. 将其粘贴到可编辑区域内的任何内容上
  3. 瞧,编辑时的滞后似乎已经消失了

大概这两个步骤都可以通过编程方式完成。

【讨论】:

    【解决方案5】:

    在所有浏览器中,元素越多,速度越慢。导致问题的另一件事是内存泄漏。大多数大型框架,如 angular 或 knockout 都会导致内存泄漏。您可以通过在内存分析器中运行内存快照来分析它们。

    就元素而言,您确实希望将其保持在 1000 以下,我希望您可以。您可以像连续滚动条一样根据需要添加和删除元素。

    【讨论】:

    • my test case 的 IE 或 Chrome 的内存占用是合理的,与 CPU 使用率相同,甚至没有达到峰值。为什么会滞后?
    • 我最近在 CKEditor 中调试了同样的问题 (dev.ckeditor.com/ticket/12062)...啊,我们已经在那里见过 :)。
    • @Reinmar,那是我的一位同事,很高兴认识你 :)
    【解决方案6】:

    我现在没有 IE 来检查性能,无论如何在 Chrome (Ubuntu) 中这确实有帮助。我只是从根元素中删除 contenteditable 并将其添加到每个 span

    这使得内容编辑非常快。

    您可以通过以下步骤检查这是 Chrome:

    1. 在 devtools(元素面板)中选择编辑器的根节点(即 bodycontenteditable 属性)

    2. 进入 devtools javascript 控制台

    3. 执行这段代码sn-p:

    片段:

    var nodes = $0.querySelectorAll('span');
    $0.setAttribute('contenteditable', false)
    for (var i = 0, max = nodes.length; i < max; i++) {
        nodes[i].setAttribute('contenteditable', true);
    }
    

    【讨论】:

    • 不幸的是,文本块选择(Shift + 箭头键)在 Chrome 或 IE 中的多个 contenteditable=true SPAN 中不起作用。此外,在 IE 中使用这种方法,您无法在行之间上下导航。
    【解决方案7】:

    你说你不想使用分页,因为......

    我看不出 AJAX/分页对可编辑内容有何帮助。实际上,它是一个类似于 Word 的全功能编辑器。例如,它有一个上下文拼写检查器,它取决于光标周围的单词。或者用户如何选择跨多个页面的文本块。

    但是,您可以在允许使用这些功能的同时使用分页(或类似的东西)。基本上,您只需要加载当前相关的行。

    我知道Objective-C,这个问题和UITableViewControllers很相似。他们通过显示当前正在查看的表格元素并释放其他元素来解决这个问题。在您的情况下,您可能希望将他们的信息存储在 JavaScript 数组中。

    我的做法是创建一个loadItem 函数和一个unloadItem 函数。 loadItem 将获取项目的内容并将其添加到正文中,unloadItem 会将内容复制回数组并删除项目(可能通过设置样式visibility:hidden,但我还没有检查看看它是否有效)。

    要查找当前相关的行:

    • 屏幕上的任何内容
    • 选择中的任何内容
    • 可能出现的任何其他应显示的内容

    当线条未被选中时,离开屏幕,或任何其他使它们不再需要的东西,调用unloadItem() 并将行号/任何标识该线条的内容传递给它。

    编辑:这就是我的意思:

    for(var count=0;count<1000;count++){
      document.getElementById("main").innerHTML+="<span id='item"+count+"'>[SOME FIELD "+count+"]</span>";
    }
    
    function loadItem(number){
      document.getElementById("item"+number).style.visibility="visible";
    }
    function unloadItem(number){
      document.getElementById("item"+number).style.visibility="hidden";
    }
    
    unloadItem(1);
    unloadItem(2);
    loadItem(1);
    
    // I didn't have time to implement the rest. Basically, when a user is not viewing a line, it should be hidden. When they scroll to view it, it should show up again. I haven't tested this yet, but it should work.
    
    // There is supposed to be a bit of slowness when it loads, it is creating all the content and that is normal.
    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body contenteditable="true" id="main">
    </body>
    </html>

    【讨论】:

    • 我不知道如何实现这一切,并且仍然保持直观的 MS Word 式编辑体验。听起来像是从头开始创建一个编辑器。有这样的现有项目(例如earwicker.com/carota),但它们在大型 HTML 内容中的表现还有很多不足之处。无论如何,如果您能接受我的repro case 并通过现场概念验证(撤消/重做、多行文本流选择等)展示您的意思,我将不胜感激。
    • @Noseratio 我添加了一个示例。没有时间让一切工作,但希望它足以证明这个想法。实际上,并不需要进行很多更改。
    • 对不起,这段代码 sn-p 根本没有帮助(我知道如何控制 HTML 元素的可见性)。如果你能发布一些实际上提供与goo.gl/rFuoqn相同的用户编辑体验但没有滞后的代码,我会再奖励500。同时,我选择的解决方案是由@Teemu 在问题的 cmets 中。
    【解决方案8】:
    1. 我认为您应该使每个跨度标记可编辑,并一次显示有限数量的跨度。这将有助于更好地加载您的网页。并且内容将很容易编辑。
    2. 此外,如果用户想要同时编辑多个跨度标签,您可以执行 editableContent="true"。这有点令人惊讶,因为如果您的文件包含 200k 大小,那么很少有人会同时编辑多个内容。每当用户单击编辑整个网页时,使用简单的基本 html 布局创建一个弹出窗口,让用户更改他想要的任何内容。它将在基本布局弹出窗口中正确加载。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-14
      • 2010-10-06
      • 1970-01-01
      • 2014-06-03
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 2012-02-22
      相关资源
      最近更新 更多