目标:
优化需要在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元素,而不是尝试一次渲染所有元素.
I have found that if the number of records in the grid becomes more then just a few thousands the grid gets very slow because the rendering speed is directly related to the number of nodes in the DOM. If the number of nodes in the DOM is more then 40-50k (depending on your computer configuration and amount of memory),your browser will crash or will become unresponsive.
So,I decided to set out on a quest to do two things: (1) dynamically create records as user scrolls (2) optimize grid to handle large data sets. After a few weeks of work,the grid was optimized and ready for testing.
我认为这与我的第一个想法类似,但我还没有尝试过这种方法.
我希望有类似经历的人可以提供一些建议,或者提供一些额外的想法.
在有人要求之前,我不能显示这些数据,它需要是用户可编辑的,它不需要突出显示代码或显示行号.最后,整个文本文件正在将FileReader加载到变量中.
我想避免将文件上传到我的网络服务器,如果可能的话,最终用户隐私和NDA问题.
服务器配置:Ubuntu 16.04 LAPP Stack与Laravel 5.4,虽然对NodeJS解决方案开放.允许使用jQuery.
提议的解决方案:
Lazy Loading – 当用户滚动时,一次只显示300行“块”.在这种情况下,需要提前使滚动条适当的高度. – 此外,应该在用户滚动时卸载这些“块”以减少DOM渲染负载的总量.
Pseduo代码:
c_chunk = scrollpos / scrollheight * totalChunks;
chunk_block = chunk[c_chunk--] + chunk[c_chunk] + chunk[c_chunk++];
my_textarea.val(chunk_block);
对这种方法有何想法?
谢谢大家.
因此,在摸索各种想法并尝试不同的方法后,我想我最终决定使用Ace作为我的项目.我选择Ace有几个原因.
>记录良好的API,除了相当大的活跃社区外,还易于理解.
>性能,与使用大型文件的Code Mirror测试相比,Ace的性能远远优于其他性能. (500,000行,github称Ace已经测试了多达400万行.
>开箱即用的功能Ace具有更多功能,可通过少量用户设置或配置启动和运行.入门总共不到10行!
>它不支持与Code Mirror一样多的浏览器,但我的项目使用WebGL运行,所以我不是很担心.
所以你理解我的理由,你想让Ace自己运行起来吗?简单,只需跳到build repo,然后根据您的需求选择一种风味.我抓住了src-min版本,因为我将它添加到我的构建脚本中.
然后以任何方式包含javascript文件:
< script src =“/ ace / ace.js”type =“text / javascript”charset =“utf-8”>< / script>
和id =“editor”的页面元素.在我的情况下,我会将它直接附加到div:
< div id =“editor”>您想要自动显示的任何文字< / 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替换了整个设置.到目前为止,编辑真的很感动!
这是他们的“操作指南”的链接:https://ace.c9.io/#nav=howto
及其API参考(非常有用):https://ace.c9.io/#nav=api