通过在textarea

时间:2017-04-28 22:54:17

标签: javascript jquery html textarea

目标:

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

目前,在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时我也注意到了大量的内容。

This site seems to tackle a similar example通过动态创建和显示dom元素,而不是尝试一次渲染所有元素。

  

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

     

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

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

我希望有过类似经历的人可以就哪条路径提出一些建议,或提供一些额外的想法。

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

如果可能的话,我希望避免将文件上传到我的网络服务器以获取最终用户隐私和NDA问题。

服务器配置:带有Laravel 5.4的Ubuntu 16.04 LAPP协议栈,虽然对NodeJS解决方案开放。允许使用jQuery。

提议的解决方案:

Lazy Loading - 只显示300行&#34;块&#34;在用户滚动时一次。在这种情况下,需要提前使滚动条适当的高度。 - 此外,应该卸载这些&#34;块&#34;当用户滚动以减少DOM渲染负载时。

Pseduo代码:

c_chunk = scrollpos / scrollheight * totalChunks;
chunk_block = chunk[c_chunk--] + chunk[c_chunk] + chunk[c_chunk++];
my_textarea.val(chunk_block);

对这种方法有何看法?

谢谢大家。

1 个答案:

答案 0 :(得分:3)

正如我所承诺的那样,我的解决方案:

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

  1. 除了相当大且活跃的社区之外,还有很好的文档化API。
  2. 性能,与使用大型文件的Code Mirror测试相比,Ace的性能远远优于其他性能。 (500,000行,github表示,Ace已通过 400万行测试。
  3. 开箱即用的功能Ace具有更多功能,可让您轻松启动并运行少量用户设置或配置。入门总共不到10行!
  4. 它不支持与Code Mirror一样多的浏览器,但是我的项目使用WebGL运行,所以我并不十分担心。
  5. 所以你理解我的理由,你想让Ace自己运行起来吗?很简单,只需跳到build repo并抓住您需要的任何一种风味。我抓住了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;
    

    如果您只是想环顾四周,看看有哪些语言/主题/选项/等等。可用,只需转到Ace's kitchen sink page并与编辑一起玩。

    现在我还需要一些功能,例如能够将文件加载到文本区域 - 您可以使用以下功能执行此操作:

    加载本地文件:

    // 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);
    }
    

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

    有大量的事件和属性可以插入并混乱,以便根据您的喜好调整此编辑器。它们都非常直接且易于使用,所以如果你不确定,那么值得花时间试一试。

    我浪费了2天尝试使用clusterize + highlightjs来处理我的设置并最终放弃,并在不到一天的时间内用Ace取代了整个设置。到目前为止,编辑真的很感动!

    这是指向他们的&#34;操作指南&#34;:https://ace.c9.io/#nav=howto的链接 及其API参考(非常有用):https://ace.c9.io/#nav=api