解析dom元素的更有效方法?

Tyl*_*coe 1 javascript dom

我有一些我需要解析的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)

编辑:
这样的系统的一个例子是谷歌文档.

当用户将文本粘贴到文档中时,它首先在屏幕上呈现,然后使用与此类似的函数(我假设)进行处理.然后它重新打印文档中的文本.这一切都发生得非常快(除非文字很长).

Fel*_*ing 5

看来你是直接将新元素插入到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)