优化需要在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);
对这种方法有何看法?
谢谢大家。
答案 0 :(得分:3)
正如我所承诺的那样,我的解决方案:
因此,在摸索各种想法并尝试不同的方法之后,我想我最终决定使用Ace作为我的项目。我选择Ace的原因有几个。
所以你理解我的理由,你想让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