可编辑的HTML内容在很大时非常滞后

时间:2023-01-06 21:35:41

For example, I have the following simple HTML page, where the <span>[SOME FIELD]</span> is repeating many times to make up for about 200K of the file size:

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

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

As the content grows, the editing experience is becoming very laggy. It's literally impossible to type or edit the content.

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

Here is a complete repro case. To see what I mean, just move the cursor to the end of the editable content and try editing. It lags big time under IE and Chrome, making it almost impossible to type. It works great under Firefox, though.

这是一个完整的repro案例。要查看我的意思,只需将光标移动到可编辑内容的末尾并尝试编辑即可。在IE和Chrome下它落后很长时间,几乎不可能打字。但它在Firefox下运行良好。

The problem: I need to get it working reasonably fast under IE.

问题:我需要在IE下合理快速地运行它。

So far, I got close with IE8 emulation (with <meta http-equiv="X-UA-Compatible" content="IE=8">), so this works (under IE).

到目前为止,我接近IE8仿真(使用 ),所以这可行(在IE下)。

However, I need to support IE=edge, too. Any advice on how to make this happen would be greatly appreciated. IMO, it's a bug (which I submitted here for IE and here for Chrome), but I'm looking for any workaround.

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

Updated, a bounty is offered for any solution that works while loaded in stand-alone IE browser or a custom application hosting WebBrowser control, using IE=edge HTML document mode.

更新后,为使用IE = edge HTML文档模式在独立IE浏览器或托管WebBrowser控件的自定义应用程序中加载的任何解决方案提供了赏金。

Updated, the corresponding IE bug reported was just closed as "Won't fix".

更新后,报告的相应IE错误刚刚关闭为“无法修复”。

8 个解决方案

#1


3  

Selecting a character with mouse or SHIFT + ARROW and then deleting by hitting DELETE will return the editing speed to normal in IE.

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

#2


3  

Why not break the data down and store it in an array or Json object and only read a portion at a time, updating as the user scrolls or moves through the content. This way only a small portion will being processed at any point in time. If you use Jquery you could get the id from the class reference. If you don't want to use Jquery you could write a class identifier function in raw Javascript. The below is rough but you can get the idea.

为什么不将数据分解并将其存储在数组或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>

#3


2  

One solution would be to not use contenteditable = true for entire area (body section in your case). You can determine the visible area of the body, create a 'Range' for the respective area and temporarily wrap it in an element with contenteditable = true.

一种解决方案是不对整个区域使用contenteditable = true(在您的情况下为body部分)。您可以确定主体的可见区域,为相应区域创建“范围”,并将其临时包装在具有contenteditable = true的元素中。

However, depending on more detailed requirements, this approach might not be suitable. For example, one problem that comes to my mind is trying to maintain caret position after scrolling only a few rows.

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

#4


2  

After a lot of blind shooting, I think I've found something that might actually work:

经过大量的盲目射击后,我想我发现了一些可能有效的东西:

  1. Copy the large chunk of HTML into the clipboard
  2. 将大块HTML复制到剪贴板中

  3. Paste it over whatever content is inside the editable area
  4. 将其粘贴到可编辑区域内的任何内容上

  5. Voilà, the lagging while editing seems to have been gone
  6. Voilà,编辑时的滞后似乎已经消失了

Presumably, both steps can be done programmatically.

据推测,这两个步骤都可以通过编程方式完成。

#5


1  

In all browsers the more elements the slower they get. The other thing that causes problems are memory leaks. Most large frameworks, like angular or knockout cause memory leaks. You can profile those by running a memory snapshot in the memory profiler.

在所有浏览器中,元素越多,它们就越慢。导致问题的另一个原因是内存泄漏。大多数大型框架(如角度或敲除)会导致内存泄漏。您可以通过在内存分析器中运行内存快照来分析这些内容。

As far as elements you really want to keep that under a thousand I'd you can. You can add and remove elements as needed they way good continuous scrollers do.

至于你真正希望保持千分之一以下的元素我就可以。您可以根据需要添加和删除元素,就像好的连续卷轴一样。

#6


1  

I have no IE to check performance right now, anyway in Chrome (Ubuntu) this do help. I just remove contenteditable from root element and add it to each span.

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

This make content editing pretty fast.

这使得内容编辑速度非常快。

You can check this is Chrome with next steps:

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

  1. in devtools (elements panel) select root node of editor (that is body with contenteditable attribute)

    在devtools(元素面板)中选择编辑器的根节点(即具有contenteditable属性的主体)

  2. got to devtools javascript console

    得到devtools javascript控制台

  3. execute this code snippet:

    执行此代码段:

Snippet:

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

#7


0  

You said that you didn't want to use pagination because...

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

I can't see how AJAX/pagination can help with editable content. In reality, it's a full-featured editor similar to Word. E.g, it has a contextual spellchecker, which depends on the words around the cursor. Or how the user can select a block of text that spans multiple pages.

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

However, you can use pagination (or something similar) while still allowing these features. Basically, you need to only load the currently relevant lines.

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

I know Objective-C, and this problem is very similar to UITableViewControllers. They combat the issue by displaying the table elements that are currently being viewed, and deallocating the others. In your case, you would want to store their information in a JavaScript array.

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

The way I would go about it is to create a loadItem function and an unloadItem function. loadItem would get the contents of an item and add it to the body, and unloadItem would copy the contents back to the array and remove the item (probably by setting the style visibility:hidden, but I haven't checked to see if it works).

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

To find the currently relevant lines:

要查找当前相关的行:

  • Anything that is on the screen
  • 屏幕上的任何内容

  • Anything that is part of a selection
  • 任何选择的一部分

  • Anything else that might come up that should be displayed
  • 应该显示的任何其他可能出现的内容

As lines are unselected, go off the screen, or anything else that renders them no longer needed, call unloadItem() and pass it the line number/whatever identifies the line.

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

EDIT: This is what I mean:

编辑:这就是我的意思:

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>

#8


-1  

  1. I think you should make each span tag editable and show limited number of spans at a time . this will help in better loading of your web page. and content will be easily editable .
  2. 我认为你应该让每个span标签都可以编辑,并且一次显示有限的跨度。这有助于更好地加载您的网页。和内容将很容易编辑。

  3. additionally you can do editableContent="true" if user wants to edit more than one span tag at the same time time. which is a bit surprising because if your file contains 200k size , someone will rarely edit multiple content at same time. whenever a user clicks to edit whole webpage, create a pop up with simple basic html layout and let user to change whatever he wants. it will load properly in basic layout popup window.
  4. 另外,如果用户想要同时编辑多个span标记,则可以执行editableContent =“true”。这有点令人惊讶,因为如果你的文件包含200k大小,有人很少会同时编辑多个内容。每当用户点击编辑整个网页时,创建一个简单的基本html布局弹出窗口,让用户更改他想要的任何内容。它将在基本布局弹出窗口中正确加载。

#1


3  

Selecting a character with mouse or SHIFT + ARROW and then deleting by hitting DELETE will return the editing speed to normal in IE.

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

#2


3  

Why not break the data down and store it in an array or Json object and only read a portion at a time, updating as the user scrolls or moves through the content. This way only a small portion will being processed at any point in time. If you use Jquery you could get the id from the class reference. If you don't want to use Jquery you could write a class identifier function in raw Javascript. The below is rough but you can get the idea.

为什么不将数据分解并将其存储在数组或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>

#3


2  

One solution would be to not use contenteditable = true for entire area (body section in your case). You can determine the visible area of the body, create a 'Range' for the respective area and temporarily wrap it in an element with contenteditable = true.

一种解决方案是不对整个区域使用contenteditable = true(在您的情况下为body部分)。您可以确定主体的可见区域,为相应区域创建“范围”,并将其临时包装在具有contenteditable = true的元素中。

However, depending on more detailed requirements, this approach might not be suitable. For example, one problem that comes to my mind is trying to maintain caret position after scrolling only a few rows.

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

#4


2  

After a lot of blind shooting, I think I've found something that might actually work:

经过大量的盲目射击后,我想我发现了一些可能有效的东西:

  1. Copy the large chunk of HTML into the clipboard
  2. 将大块HTML复制到剪贴板中

  3. Paste it over whatever content is inside the editable area
  4. 将其粘贴到可编辑区域内的任何内容上

  5. Voilà, the lagging while editing seems to have been gone
  6. Voilà,编辑时的滞后似乎已经消失了

Presumably, both steps can be done programmatically.

据推测,这两个步骤都可以通过编程方式完成。

#5


1  

In all browsers the more elements the slower they get. The other thing that causes problems are memory leaks. Most large frameworks, like angular or knockout cause memory leaks. You can profile those by running a memory snapshot in the memory profiler.

在所有浏览器中,元素越多,它们就越慢。导致问题的另一个原因是内存泄漏。大多数大型框架(如角度或敲除)会导致内存泄漏。您可以通过在内存分析器中运行内存快照来分析这些内容。

As far as elements you really want to keep that under a thousand I'd you can. You can add and remove elements as needed they way good continuous scrollers do.

至于你真正希望保持千分之一以下的元素我就可以。您可以根据需要添加和删除元素,就像好的连续卷轴一样。

#6


1  

I have no IE to check performance right now, anyway in Chrome (Ubuntu) this do help. I just remove contenteditable from root element and add it to each span.

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

This make content editing pretty fast.

这使得内容编辑速度非常快。

You can check this is Chrome with next steps:

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

  1. in devtools (elements panel) select root node of editor (that is body with contenteditable attribute)

    在devtools(元素面板)中选择编辑器的根节点(即具有contenteditable属性的主体)

  2. got to devtools javascript console

    得到devtools javascript控制台

  3. execute this code snippet:

    执行此代码段:

Snippet:

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

#7


0  

You said that you didn't want to use pagination because...

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

I can't see how AJAX/pagination can help with editable content. In reality, it's a full-featured editor similar to Word. E.g, it has a contextual spellchecker, which depends on the words around the cursor. Or how the user can select a block of text that spans multiple pages.

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

However, you can use pagination (or something similar) while still allowing these features. Basically, you need to only load the currently relevant lines.

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

I know Objective-C, and this problem is very similar to UITableViewControllers. They combat the issue by displaying the table elements that are currently being viewed, and deallocating the others. In your case, you would want to store their information in a JavaScript array.

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

The way I would go about it is to create a loadItem function and an unloadItem function. loadItem would get the contents of an item and add it to the body, and unloadItem would copy the contents back to the array and remove the item (probably by setting the style visibility:hidden, but I haven't checked to see if it works).

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

To find the currently relevant lines:

要查找当前相关的行:

  • Anything that is on the screen
  • 屏幕上的任何内容

  • Anything that is part of a selection
  • 任何选择的一部分

  • Anything else that might come up that should be displayed
  • 应该显示的任何其他可能出现的内容

As lines are unselected, go off the screen, or anything else that renders them no longer needed, call unloadItem() and pass it the line number/whatever identifies the line.

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

EDIT: This is what I mean:

编辑:这就是我的意思:

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>

#8


-1  

  1. I think you should make each span tag editable and show limited number of spans at a time . this will help in better loading of your web page. and content will be easily editable .
  2. 我认为你应该让每个span标签都可以编辑,并且一次显示有限的跨度。这有助于更好地加载您的网页。和内容将很容易编辑。

  3. additionally you can do editableContent="true" if user wants to edit more than one span tag at the same time time. which is a bit surprising because if your file contains 200k size , someone will rarely edit multiple content at same time. whenever a user clicks to edit whole webpage, create a pop up with simple basic html layout and let user to change whatever he wants. it will load properly in basic layout popup window.
  4. 另外,如果用户想要同时编辑多个span标记,则可以执行editableContent =“true”。这有点令人惊讶,因为如果你的文件包含200k大小,有人很少会同时编辑多个内容。每当用户点击编辑整个网页时,创建一个简单的基本html布局弹出窗口,让用户更改他想要的任何内容。它将在基本布局弹出窗口中正确加载。