Javascript 一种更有效的解析dom元素的方法?
我有一些HTML需要解析 基本上,我正在遍历给定元素的dom。抓取文本节点和元素节点 当我遇到文本节点时,我会逐个字符地将它们打印到不同的元素中。每个字符都被放置在自己的范围内,并具有自己的样式,该样式取自任何附加样式的元素节点 因此,当找到一个元素节点时,它的样式将应用于检测到的任何文本节点,直到找到另一个元素节点并用新样式替换旧样式 下面的代码可以工作。如果源元素中有一个句子或短段落,它会在不到一秒钟的时间内准确地复制文本。文本越长,花费的时间就越长(duh) 有趣的是,目标元素中已经存在的文本越多,花费的时间就越长。因此,如果我在同一个源元素上运行了10次这个函数,并且处理了相同的文本体,那么第10次到第1次到第10次的运行速度会比第1次到第1次慢,这可能是因为在一个已经有内容的元素中渲染文本比较困难 不管怎样,我真的需要找到一种方法让它运行得更快 最后,这是一个可能需要处理的HTML代码片段示例:Javascript 一种更有效的解析dom元素的方法?,javascript,dom,Javascript,Dom,我有一些HTML需要解析 基本上,我正在遍历给定元素的dom。抓取文本节点和元素节点 当我遇到文本节点时,我会逐个字符地将它们打印到不同的元素中。每个字符都被放置在自己的范围内,并具有自己的样式,该样式取自任何附加样式的元素节点 因此,当找到一个元素节点时,它的样式将应用于检测到的任何文本节点,直到找到另一个元素节点并用新样式替换旧样式 下面的代码可以工作。如果源元素中有一个句子或短段落,它会在不到一秒钟的时间内准确地复制文本。文本越长,花费的时间就越长(duh) 有趣的是,目标元素中已经存在的
<span style='blah: blah;'> Some text </span><span>Even more text </span> <p> stuff </p>
一些文本甚至更多文本东西
生成的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>
.......
S
o
M
E
T
E
x
T
.......
没什么特别的
代码如下:
代码:
ed.rta\u to\u arr\u paste=函数(ele,cur\u样式){
var child_arr=ele.childNodes;
如果(!(已设置(当前样式))){
cur_style={};
}
对于(变量i=0;i
编辑:谷歌文档就是这样一个例子 当用户将文本粘贴到文档中时,它首先在屏幕外呈现,然后使用与此类似的函数(我假设)进行处理。然后重新打印文档中的文本。
这一切发生得非常快(除非文本很长)。看起来每次调用都在DOM中搜索一个元素。我认为您应该将事件附加到类似onload的DOM元素中(或者更好地使用jquery document.ready)。在调用for循环之前,我还要(作为一个小的重构)首先检查以确保您有子元素(child_arr.length>0)(这可能是完全不重要的,但最佳实践)看起来您在每次调用时都在DOM中搜索一个元素。我认为您应该将事件附加到类似onload的DOM元素中(或者更好地使用jquery document.ready)。在调用for循环之前,我还要(作为一个小的重构)首先检查确保您有子对象(child_arr.length>0)(这可能是完全不重要的,但却是最佳实践)看起来您是在直接将新元素插入DOM树,所以我认为您可以通过不这样做获得最佳改进 避免逐个插入大量元素。每次插入元素时,浏览器都必须重新计算页面布局,这需要时间 相反,将节点添加到不在DOM中的元素中,最好使用,可以通过创建 然后你所要做的就是插入这个片段,浏览器只需要重新计算一次 更新: 您还可以尝试使用正则表达式将文本转换为
span
元素
var html = value.replace(/(.)/g, "<span>$1</span>")
似乎您正在直接将新元素插入DOM树中,因此我认为您可以通过不这样做获得最佳的改进 避免逐个插入大量元素。每次插入元素时,浏览器都必须重新计算页面布局,这需要时间 相反,将节点添加到不在DOM中的元素中,最好使用,可以通过创建 然后你所要做的就是插入这个片段,浏览器只需要重新计算一次 更新: 您还可以尝试使用正则表达式将文本转换为
span
元素
var html = value.replace(/(.)/g, "<span>$1</span>")
你能提供一个演示吗?不知怎的,我很难理解你想要做什么…由于保密协议特别严格,我无法发布演示。检查编辑,也许会有帮助。@Tyler:at的演示会很有帮助,即使你只是删掉专有函数,这样它们基本上可以进行相同的处理,而不暴露你的代码。
add\u single\u char
在做什么?如何将下一个字符添加到元素中?通过减少元素的属性访问,您已经可以节省“一些”时间。它会将child_arr[i].nodeValue.charAt(n)处的字符添加到目标元素(在本例中为div)。它会返回为包含该字符而创建的跨度。您能提供一个演示吗?不知怎的,我很难理解你想要做什么…由于保密协议特别严格,我无法发布演示。检查编辑,也许会有帮助。@Tyler:at的演示会很有帮助,即使你只是删掉专有函数,这样它们基本上可以进行相同的处理,而不暴露你的代码。add\u single\u char
在做什么?如何将下一个字符添加到元素中?您已经可以通过减少元素的属性访问来节省“一些”时间。它将child_arr[i].nodeValue.charAt(n)处的字符添加到目标元素中,在本例中该元素是div。它返回在
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);
}
}
}
}