我有一些我需要解析的HTML.
基本上我正在走过一个给定元素的dom.抓取文本节点和元素节点.
当我遇到文本节点时,我会逐个字符地将它们打印成不同的元素.每个角色都放置在自己的跨度中,具有自己的样式,该样式取自任何附加样式的元素节点.
因此,当找到元素节点时,它的样式将应用于检测到的任何文本节点,直到找到另一个元素节点并将旧样式替换为新样式.
以下代码有效.如果源元素中有句子或短段落,则会在不到一秒的时间内准确地再现文本.文本越长,花费的时间越长(duh).
有趣的是,目标元素中已经存在的文本越多,所需的时间就越长.因此,如果我在相同的源元素上运行此函数10次,并且处理相同的文本正文,那么它将比第1次运行速度慢第10次,可能是因为在元素中渲染文本更难那已经有了内容.
无论如何,我真的需要找到一种方法来使这个东西运行得更快.
最后,这是一个示例HTML代码段,可能需要处理:
<span style='blah: blah;'> Some text </span><span>Even more text </span> <p> stuff </p>
Run Code Online (Sandbox Code Playgroud)
生成的HTML将是:
<span style='blah: blah;'>S</span>
<span style='blah: blah;'>o</span>
<span style='blah: blah;'>m</span>
<span style='blah: blah;'>e</span>
<span style='blah: blah;'> </span>
<span style='blah: blah;'>t</span>
<span style='blah: blah;'>e</span>
<span style='blah: blah;'>x</span>
<span style='blah: blah;'>t</span>
.......
Run Code Online (Sandbox Code Playgroud)
没有什么花哨.
这是代码:
码:
ed.rta_to_arr_paste = function(ele, cur_style) {
var child_arr = ele.childNodes;
if(!(is_set(cur_style))) {
cur_style = {};
}
for(var i = 0; i < child_arr.length; i++) {
if(child_arr[i].nodeType == 1) {
if(cur_style != child_arr[i].style) {
cur_style = child_arr[i].style;
}
} else if(child_arr[i].nodeType == 3) {
for(var n = 0; n < child_arr[i].nodeValue.length; n++) {
var span = ed.add_single_char(child_arr[i].nodeValue.charAt(n), cur_style);
}
}
ed.rta_to_arr_paste(child_arr[i], cur_style);
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
这样的系统的一个例子是谷歌文档.
当用户将文本粘贴到文档中时,它首先在屏幕上呈现,然后使用与此类似的函数(我假设)进行处理.然后它重新打印文档中的文本.这一切都发生得非常快(除非文字很长).
看来你是直接将新元素插入到DOM树中,所以我认为你可以通过不这样做来获得最好的改进.
避免逐个插入大量元素.每次插入元素时,浏览器都必须重新计算页面的布局,这需要时间.
相反,将节点添加到不在DOM中的元素,最好的是使用a DocumentFragment,可以通过创建document.createDocumentFragment.
然后你所要做的就是插入这个片段,浏览器只需重新计算一次.
更新:
您还可以尝试使用正则表达式将文本转换为span元素.
var html = value.replace(/(.)/g, "<span>$1</span>")
Run Code Online (Sandbox Code Playgroud)
至少在我的天真测试中(不确定测试用例是否这样好),它比创建span元素并将它们添加到文档片段要好得多:
更新2:我调整了测试以将生成的元素/字符串设置为元素的内容,遗憾的是,这会消除所有使用速度replace.但它可能仍值得测试:
http://jsperf.com/regex-vs-loop
您还应该避免重复访问属性:
ed.rta_to_arr_paste = function(ele, cur_style) {
var child_arr = ele.childNodes;
if(!(is_set(cur_style))) {
cur_style = {};
}
for(var i = 0, l = child_arr; i <l; i++) {
var child = child_arr[i];
if(child.nodeType == 1) {
// this will always be true, because `el.style` returns an object
// so comparing it does not make sense. Maybe just override it always
if(cur_style != child.style) {
cur_style = child.style;
}
// doesn't need to be called for other nodes
ed.rta_to_arr_paste(child, cur_style);
}
else if(child.nodeType == 3) {
var value = child.nodeValue;
for(var n = 0, ln = value.length; n < ln; n++) {
ed.add_single_char(value.charAt(n), cur_style);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1815 次 |
| 最近记录: |