有没有一种方法可以仅获取顶层元素的innerText(并忽略子元素的innerText)?

32
有没有办法仅获取顶级元素的innerText(并忽略子元素的innerText)?
示例:
<div> 
   top node text 
   <div> child node text </div>
</div>

如何获取“顶层节点文本”,同时忽略“子节点文本”?innerText属性似乎返回顶部div的内部文本和子元素文本的拼接。


1
先删除非文本直接子节点? - Oded
2
@Oded:不需要。只需遍历子元素并连接即可。非常简单。 - Tim Down
7个回答

30

只需遍历子节点并连接文本节点即可:

var el = document.getElementById("your_element_id"),
    child = el.firstChild,
    texts = [];

while (child) {
    if (child.nodeType == 3) {
        texts.push(child.data);
    }
    child = child.nextSibling;
}

var text = texts.join("");

1
+1 显然比克隆可能非常庞大的DOM树要好,只是为了丢弃其中大部分。唯一的改进是在开始时设置text = [],然后每次迭代使用text.push(child.data),最后使用text = text.join('')将片段数组转换为字符串,在重复连接到不断增长的字符串上,这往往比较快。 - Daniel Earwicker
@DanielEarwicker:我考虑过这个,但是我看到的最新基准测试表明,它并没有明显提高性能,所以我选择了更简单的版本。我现在会再检查一下。 - Tim Down
1
不错。PS。data是在CharacterData接口中定义的,该接口由Text(文本节点)实现。 - Rob W
1
@DanielEarwicker:似乎在现代浏览器中,数组连接可能会更慢,但在IE 7中速度要快得多,这超越了一切,因为你最慢的目标浏览器是你实际需要提高性能的地方。进行修改... - Tim Down
1
你可以使用Node.TEXT_NODE代替3 来源(请参阅命名常量) - William Ardila
1
@WilliamArdila:没错。除了2012年之前的IE <= 8,当时还没有消失。 - Tim Down

13

这段代码可以在您的示例中正常工作:document.getElementById("item").firstChild.nodeValue;

注意:请记住,如果您知道自己正在处理特定的HTML,则此方法可行。如果您的HTML可能会发生变化,例如:

<div> 
    <div class="item"> child node text </div>
    top node text 
</div>

如果您想要更通用的解决方案,则应使用@Tim Down提供的方法。


以下是可工作的代码片段:

window.onload = function() {
   var text = document.getElementById("item").firstChild.nodeValue;
   document.getElementById("result").innerText = text.trim();
};
#result {
  border: 1px solid red;
}
<div id="item">
  top node text 
   <div> child node text </div>
</div>



<strong>Result:</strong> <div id="result"></div>


4
  1. 克隆元素。
  2. 向后循环所有子节点(以避免冲突):
    如果元素有tagName属性,则它是一个元素:删除该节点。
  3. 使用innerText获取文本内容(当不支持innerText时,回退到textContent)。

代码:

var elem = document.getElementById('theelement');
elem = elem.cloneNode(true);
for (var i=elem.childNodes.length-1; i>=0; i--) {
    if (elem.childNodes[i].tagName) elem.removeChild(elem.childNodes[i]);
}
var innerText = elem['innerText' in elem ? 'innerText' : 'textContent'];

哇,所有浏览器都能像魔法般地工作。坦白说,在发布问题之前,我认为这是不可能的 :) …谢谢... - ivymike
2
不需要克隆或改变DOM。只需读取文本节点子元素即可。请参见我的答案。 - Tim Down
3
@ivymike的方法更好,我建议接受他的答案而不是我的。它也适用于所有浏览器(在IE6+、Chrome 1+、Safari 5和Firefox 3+中测试过)。 - Rob W

3

function getDirectInnerText(element) {
  var childNodes = element.childNodes;
  result = '';

  for (var i = 0; i < childNodes.length; i++) {
    if(childNodes[i].nodeType == 3) {
      result += childNodes[i].data;
    }
  }

  return result;
}

element = document.querySelector("div#element");
console.log(getDirectInnerText(element))
<div id="element"> 
   top node text 
   <div> child node text </div>
</div>


避免只提供代码答案。 此外,您可以将 3 更改为 Node.TEXT_NODE,以减少常量使用并提高可读性。 - LukasKroess

0
如果您不想忽略子元素的内部文本,请使用以下函数:
function getInnerText(el) {
    var x = [];
    var child = el.firstChild;
    while (child) {
        if (child.nodeType == 3) {
            x.push(child.nodeValue);
        }
        else if (child.nodeType == 1) {
            var ii = getInnerText(child);
            if (ii.length > 0) x.push(ii);
        }
        child = child.nextSibling;
    }
    return x.join(" ");
}

2
我有什么遗漏,还是这与他们所要求的相反? - Tom

0

正如其他答案已经解释的那样,您需要检查子节点的类型。

这是一个基于@ehsaneha's answer的简洁一行代码:

Array.from(element.childNodes).reduce((x, y) => x + (y.nodeType == Node.TEXT_NODE ? y.data : ''), '').trim()

或者作为一个原型方法:
Element.prototype.directInnerText = function () {
    return Array.from(this.childNodes).reduce((x, y) => x + (y.nodeType == Node.TEXT_NODE ? y.data : ''), '').trim();
}

用法:

console.log(document.body.querySelector('.element').directInnerText());

兼容性参考:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType?retiredLocale=de


0
const nodeValues=[];
document.querySelectorAll("locator").forEach(
    function (currentValue) {
        nodeValues.push(currentValue.firstChild.nodeValue);
    }
)
return nodeValues;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接