Javascript textNodes的getElementsByTagName()等效项
有没有办法获取文档中所有Javascript textNodes的getElementsByTagName()等效项,javascript,dom,dhtml,textnode,Javascript,Dom,Dhtml,Textnode,有没有办法获取文档中所有textNode对象的集合 getElementsByTagName()对于元素非常有效,但是textNodes不是元素 更新:我意识到这可以通过遍历DOM来实现——正如下面许多人所建议的那样。我知道如何编写DOM walker函数来查看文档中的每个节点。我希望有一个浏览器原生的方式来做这件事。毕竟有点奇怪,我可以通过一个内置调用获得所有的s,但不是所有的textNodes。更新: 我概述了这6种方法在1000次运行中的基本性能测试getElementsByTagName
textNode
对象的集合
getElementsByTagName()
对于元素非常有效,但是textNode
s不是元素
更新:我意识到这可以通过遍历DOM来实现——正如下面许多人所建议的那样。我知道如何编写DOM walker函数来查看文档中的每个节点。我希望有一个浏览器原生的方式来做这件事。毕竟有点奇怪,我可以通过一个内置调用获得所有的
s,但不是所有的textNode
s。更新:
我概述了这6种方法在1000次运行中的基本性能测试getElementsByTagName
是最快的,但它做的工作是半途而废的,因为它不选择所有元素,而只选择一种特定类型的标记(我认为p
),并且盲目地假设它的第一个子元素是文本元素。它可能有点缺陷,但只是为了演示,并将其性能与TreeWalker
进行比较。看看结果
Text
节点。您仍然需要遍历每个生成的文本节点并调用node.nodeValue
,才能像处理任何DOM节点一样获得实际文本。因此,性能问题不是迭代文本节点,而是迭代所有非文本节点并检查其类型。我认为(基于结果),TreeWalker
的执行速度与getElementsByTagName
一样快,如果不是更快的话(即使getElementsByTagName是残疾人)
递归树遍历
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;
}
}
}
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);
}
}
}
查询选择全部
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;
}
}
}
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);
}
}
}
此外,您可能会发现此讨论很有帮助-
/*
可以返回某个父元素的所有子代文本节点的数组,
或者,您可以向它传递一些函数并执行某些操作(查找、替换或其他任何操作)
将文本放在适当的位置
此示例返回正文中非空白文本节点的文本:
var A= document.deepText(document.body, function(t){
var tem= t.data;
return /\S/.test(tem)? tem: undefined;
});
alert(A.join('\n'))
*/
方便搜索和替换、突出显示等我知道你特别要求收藏,但如果你只是非正式地说,而不关心它们是否都被合并成一个大字符串,你可以使用:
var allTextAsString = document.documentElement.textContent || document.documentElement.innerText;
…第一项是DOM3标准方法。但是请注意,innerText
似乎排除了支持它的实现中的脚本或样式标记内容(至少是IE和Chrome),而textContent
包括它们(在Firefox和Chrome中)。var el1=document.childNodes[0]
函数get(节点,ob)
{
ob=ob |{};
if(node.childElementCount)
{
ob[node.nodeName]={}
ob[node.nodeName][“text”]=[];
对于(var x=0;x
这是最快的TreeWalker方法的现代版迭代器:
function getTextNodesIterator(el) { // Returns an iterable TreeWalker
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
walker[Symbol.iterator] = () => ({
next() {
const value = walker.nextNode();
return {value, done: !value};
}
});
return walker;
}
用法:
for (const textNode of getTextNodesIterator(document.body)) {
console.log(textNode)
}
更安全的版本
如果在循环时移动节点,直接使用迭代器可能会卡住。这样更安全,它返回一个数组:
function getTextNodes(el) { // Returns an array of Text nodes
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const nodes = [];
while (walker.nextNode()) {
nodes.push(walker.currentNode);
}
return nodes;
}
这里有一个更为惯用且(希望)更容易理解的替代方案 函数getText(节点){ //递归到每个子节点 if(node.hasChildNodes()){ node.childNodes.forEach(getText); } //获取每个非空文本节点的内容 else if(node.nodeType===node.TEXT\u node){ const text=node.textContent.trim(); 如果(文本){ console.log(text);//做点什么 } } }
在createTreeWalker
被弃用后,您可以使用
/**
*获取元素下的所有文本节点
*@param{!Element}el
*@return{Array}
*/
函数getTextNodes(el){
常量迭代器=document.createNodeIterator(el,NodeFilter.SHOW_TEXT);
常量textNodes=[];
让currentTextNode;
而((currentTextNode=iterator.nextNode()){
push(currentTextNode);
}
返回文本节点;
}
我在不同的浏览器中获得了上述每种方法的混合结果-以上这些结果是针对Chrome的。Firefox和Safari的行为非常不同。不幸的是,我没有访问IE的权限,但你们可以自己在IE上测试一下,看看它是否有效。至于浏览器优化,我不担心为每个浏览器选择不同的方法,只要差异在几十毫秒甚至几百毫秒左右。这是一个非常有用的答案,但要注意,不同的方法返回的结果非常不同。如果它们是父节点的第一个子节点,那么它们中的许多只会获得文本节点。其中一些节点只能获取文本,而其他节点只需稍作修改即可返回实际的文本节点。迭代树遍历中存在可能影响其性能的错误。将node.nodeType=3
更改为node.nodeType==3
@theazureshadow-感谢您指出了突出的=
错误。我已经解决了这个问题,xpath版本只是返回Text
对象,而不是像其他版本一样返回其中包含的实际字符串
function getTextNodesIterator(el) { // Returns an iterable TreeWalker
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
walker[Symbol.iterator] = () => ({
next() {
const value = walker.nextNode();
return {value, done: !value};
}
});
return walker;
}
for (const textNode of getTextNodesIterator(document.body)) {
console.log(textNode)
}
function getTextNodes(el) { // Returns an array of Text nodes
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
const nodes = [];
while (walker.nextNode()) {
nodes.push(walker.currentNode);
}
return nodes;
}