通过在textarea中部分显示数据来动态显示大量文本

Xan*_*ano 5 html javascript jquery textarea

目标:

优化需要在textarea内容中编辑大量文本数据(25mb +)或可编辑内容的网页div,而不会丢失太多性能.

目前,在Chrome上加载10mb文件大约需要3秒钟.我希望这最多1秒.


想法和尝试:

我正在使用用户计算机加载本地文本文件,<input type="file">并且没有问题将大文件直接加载到内存中.但是,当我尝试在textarea中显示此文本数据时,我自然会遇到性能问题.

我有拼写检查,自动大写和自动完成所有禁用,这肯定有帮助,但我想尽量减少尝试渲染大文件时的滞后量(文件大于10mb,最大100mb将是理想的).

<textarea autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false">

我的一个想法是只渲染前100行和当前行后100行,当用户滚动textarea时,我会切换出正在显示的数据.我可以交换几百行没有任何明显的延迟,但成千上万的人锁定了整个页面.

我还在研究CodeMirror等项目,这些项目在一些基于javascript的文本编辑器和chrome dev工具中使用.但是,在最初加载大量文本时,快速测试显示出类似的性能问题.

另一个想法是使用highlight.js来渲染文本dom元素,但在处理数以千计的DOM elemet时我也注意到了大量的内容.

这个网站似乎通过动态创建和显示dom元素来解决类似的例子,而不是尝试一次渲染所有元素.

我发现,如果网格中的记录数量变得更多,那么网格变得非常慢,因为渲染速度与DOM中的节点数量直接相关.如果DOM中的节点数超过40-50k(取决于您的计算机配置和内存量),您的浏览器将崩溃或无响应.

所以,我决定开始做两件事:(1)动态创建记录作为用户滚动(2)优化网格来处理大数据集.经过几周的工作,网格已经过优化,可以进行测试.

我认为这与我的第一个想法类似,但我还没有尝试过这种方法.

我希望有类似经历的人可以提供一些建议,或者提供一些额外的想法.

在有人要求之前,我不能显示这些数据,它需要是用户可编辑的,它不需要突出显示代码或显示行号.最后,整个文本文件正在将FileReader加载到变量中.

我想避免将文件上传到我的网络服务器,如果可能的话,最终用户隐私和NDA问题.

服务器配置:Ubuntu 16.04 LAPP Stack与Laravel 5.4,虽然对NodeJS解决方案开放.允许使用jQuery.


提议的解决方案:

延迟加载 - 当用户滚动时,一次只显示300行"块".在这种情况下,需要提前使滚动条适当的高度. - 此外,应该在用户滚动时卸载这些"块"以减少DOM渲染负载的总量.

Pseduo代码:

c_chunk = scrollpos / scrollheight * totalChunks;
chunk_block = chunk[c_chunk--] + chunk[c_chunk] + chunk[c_chunk++];
my_textarea.val(chunk_block);
Run Code Online (Sandbox Code Playgroud)

对这种方法有何想法?

谢谢大家.

Xan*_*ano 8

正如所承诺的,这是我的解决方案:

所以在摸索各种想法并尝试了不同的方法之后,我想我最终决定在我的项目中使用 Ace。我选择 Ace 有几个原因。

  1. 除了相当大且活跃的社区外,文档齐全的 API 还易于理解。
  2. 性能,与我使用大文件使用 Code Mirror 进行的测试相比,Ace 的性能要高得多。(500,000 行,github 说 Ace 已经测试了多达400 万行。
  3. 开箱即用的功能 Ace 具有更多功能,让您只需很少的用户设置或配置即可启动和运行。入门总共不到 10 行!
  4. 它支持的浏览器没有 Code Mirror 那么多,但是我的项目是用 WebGL 运行的,所以我不是很担心。

所以你明白我的推理,你想让 Ace 自己运行吗?简单,只需跳到构建存储库并获取您需要的任何风格套件。我抓住了 src-min 版本,因为我将把它添加到我的构建脚本中。

然后只需以任何方式包含 javascript 文件:

<script src="/ace/ace.js" type="text/javascript" charset="utf-8"></script>

和一个元素到您的页面id="editor"。在我的情况下,我将它直接附加到一个 div:

<div id="editor">Any text you want to have auto displayed</div>

并在一个 javascript 文件中:

var editor = ace.edit("editor");
editor.setTheme("ace/theme/chrome");
editor.session.setMode("ace/mode/javascript");
editor.$blockScrolling = Infinity;
Run Code Online (Sandbox Code Playgroud)

如果你只是想看看周围有哪些语言/主题/选项/等。可用,只需前往Ace 的厨房水槽页面并与编辑器一起玩。

现在我还需要一些功能,例如能够将文件加载到文本区域 - 您可以通过以下方式做到这一点:

加载本地文件:

// Add event listener to the file input
// Note: This will not fire twice if the user opens File A, then re-opens file A
// To detect re-opening a file you will need to clear the input
// after the file is read so that it "changes" upon re-opening
document.getElementById('open-file').addEventListener('change', handleFileOpen, false);

// First we create the function handler that fires when our input is changed
function handleFileOpen(e) {
    var file = e.target.files[0]; // Get first file selected

    // Load file using file reader function
    loadFile(file);
}

function loadFile(file) {    
    // Create file reader and relevant Ace code
    var reader = new FileReader();
    reader.onload = function(e) {
        // Get text contents of file
        var data = e.target.result;

        // Update Ace Editor with loaded data
        editor.setValue(data, -1);
    };

    // Now that we defined the function we want to run, read the file
    reader.readAsText(file);
}
Run Code Online (Sandbox Code Playgroud)

setValue()函数中的 -1表示将光标放在文件的开头(顶部)- 1 将是底部。

有大量的事件和属性,您可以挂钩并弄乱,以便根据您的喜好调整此编辑器。它们都非常直接且易于使用,因此如果您犹豫不决,值得花时间尝试一下。

我浪费了 2 天的时间试图让 clusterize + highlightjs 与我的设置一起工作,但最终放弃并在不到一天的时间内用 Ace 替换了整个设置。到目前为止,编辑器给我留下了深刻的印象!

这是他们的“操作指南”链接:https : //ace.c9.io/#nav=howto
和他们的 API 参考(非常有用):https : //ace.c9.io/#nav=接口