getElementsByTagName()相当于textNodes
有没有办法获得文档中的所有textNode
对象的集合?
getElementsByTagName()
适用于元素,但textNode
不是元素。
更新:我意识到这可以通过步行的DOM – 如下面的build议。 我知道如何编写一个DOM-walker函数来查看文档中的每个节点。 我希望有一些浏览器本地的方式来做到这一点。 毕竟有一点奇怪,我可以通过一个内置的调用来获得所有的<input>
,但不是所有的textNode
。
更新 :
我已经概述了1000种运行的6种方法的基本性能testing。 getElementsByTagName
是最快的,但它做了一半的工作,因为它不select所有的元素,但只有一个特定types的标签(我认为是p
),并盲目地认为它的firstChild是一个文本元素。 它可能没有什么缺陷,但它有示范的目的,并将其性能与TreeWalker
进行比较。 在jsfiddle上自己运行testing来查看结果。
- 使用TreeWalker
- 自定义迭代遍历
- 自定义recursion遍历
- Xpath查询
- querySelectorAll
- 的getElementsByTagName
让我们暂时假定有一种方法可以让你本地获得所有的Text
节点。 您仍然必须遍历每个生成的文本节点,并调用node.nodeValue
来获取实际的文本,就像使用任何DOM节点一样。 因此,性能问题不是遍历文本节点,而是遍历所有不是文本的节点并检查其types。 我会争辩(基于结果), TreeWalker
执行速度与getElementsByTagName
一样快,如果不是更快(即使getElementsByTagName正在播放残疾人)。
每次testing1000次。 方法总计毫秒平均毫秒 -------------------------------------------------- 文件.TreeWalker 301 0.301 迭代遍历769 0.769 recursion遍历器7352 7.352 XPath查询1849 1.849 querySelectorAll 1725 1.725 getElementsByTagName 212 0.212
每种方法的来源:
TreeWalker
function nativeTreeWalker() { var walker = document.createTreeWalker( document.body, NodeFilter.SHOW_TEXT, null, false ); var node; var textNodes = []; while(node = walker.nextNode()) { textNodes.push(node.nodeValue); } }
recursion树遍历
function customRecursiveTreeWalker() { var result = []; (function findTextNodes(current) { for(var i = 0; i < current.childNodes.length; i++) { var child = current.childNodes[i]; if(child.nodeType == 3) { result.push(child.nodeValue); } else { findTextNodes(child); } } })(document.body); }
迭代树遍历
function customIterativeTreeWalker() { var result = []; var root = document.body; var node = root.childNodes[0]; while(node != null) { if(node.nodeType == 3) { /* Fixed a bug here. Thanks @theazureshadow */ result.push(node.nodeValue); } if(node.hasChildNodes()) { node = node.firstChild; } else { while(node.nextSibling == null && node != root) { node = node.parentNode; } node = node.nextSibling; } } }
querySelectorAll
function nativeSelector() { var elements = document.querySelectorAll("body, body *"); /* Fixed a bug here. Thanks @theazureshadow */ var results = []; var child; for(var i = 0; i < elements.length; i++) { child = elements[i].childNodes[0]; if(elements[i].hasChildNodes() && child.nodeType == 3) { results.push(child.nodeValue); } } }
getElementsByTagName (让分)
function getElementsByTagName() { var elements = document.getElementsByTagName("p"); var results = []; for(var i = 0; i < elements.length; i++) { results.push(elements[i].childNodes[0].nodeValue); } }
XPath的
function xpathSelector() { var xpathResult = document.evaluate( "//*/text()", document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); var results = [], res; while(res = xpathResult.iterateNext()) { results.push(res.nodeValue); /* Fixed a bug here. Thanks @theazureshadow */ } }
此外,您可能会发现这个讨论有帮助 – http://bytes.com/topic/javascript/answers/153239-how-do-i-get-elements-text-node
我知道你特别要求collections,但是如果你只是非正式的意思,并不在乎是否所有的东西都加在一起,你可以使用:
var allTextAsString = document.documentElement.textContent || document.documentElement.innerText;
第一个项目是DOM3标准方法。 但是请注意, innerText
似乎在支持它的实现(至lessIE和Chrome)中排除脚本或样式标记内容,而textContent
包含它们(在Firefox和Chrome中)。
document.deepText= function(hoo, fun){ var A= [], tem; if(hoo){ hoo= hoo.firstChild; while(hoo!= null){ if(hoo.nodeType== 3){ if(typeof fun== 'function'){ tem= fun(hoo); if(tem!= undefined) A[A.length]= tem; } else A[A.length]= hoo; } else A= A.concat(document.deepText(hoo, fun)); hoo= hoo.nextSibling; } } return A; }
/ *您可以返回某个父元素的所有后代文本节点的数组,或者您可以将其传递给某个函数,并在文本中执行某些操作(查找,replace或其他)。
此示例返回正文中非空白文本节点的文本:
var A= document.deepText(document.body, function(t){ var tem= t.data; return /\S/.test(tem)? tem: undefined; }); alert(A.join('\n'))
* /
方便search和replace,突出显示等
var el1 = document.childNodes[0] function get(node,ob) { ob = ob || {}; if(node.childElementCount) { ob[node.nodeName] = {} ob[node.nodeName]["text"] = []; for(var x = 0; x < node.childNodes.length;x++) { if(node.childNodes[x].nodeType == 3) { var txt = node.childNodes[x].nodeValue; ob[node.nodeName]["text"].push(txt) continue } get(node.childNodes[x],ob[node.nodeName]) }; } else { ob[node.nodeName] = (node.childNodes[0] == undefined ? null :node.childNodes[0].nodeValue ) } return ob } var o = get(el1) console.log(o)
下面是最快的TreeWalker方法的一个现代Iterator
版本:
function getTextNodesIterator(el) { const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT); const next = () => { const value = walker.nextNode(); return { value, done: !value }; }; walker[Symbol.iterator] = () => ({next}); return walker; }
用法:
const textNodes = [...getTextNodesIterator(document.body)];
或者更有趣的是,用for-of
循环:
for (const textNode of getTextNodesIterator(document.body)) { console.log(textNode) }