如果我有这样的html:

<li id="listItem">
    This is some text
    <span id="firstSpan">First span text</span>
    <span id="secondSpan">Second span text</span>
</li>

我试图使用.text()检索字符串“这是一些文本”,但如果我说$('#list-item').text(),我得到“这是一些textFirst span textSecond span文本”。

是否有一种方法可以获取(并可能通过.text("")之类的方法删除)标签中的自由文本,而不是其子标签中的文本?

HTML不是我写的,所以这是我必须与工作。我知道这将是简单的,只是包装标签的文本时编写的html,但再次,html是预先编写的。


当前回答

我不会为此而使用jQuery,尤其是那些对元素进行不必要克隆的解决方案。您所需要的就是一个简单的循环抓取文本节点。在现代JavaScript中(在撰写本文时,“现代”是一个移动的目标!),并从结果的开头和结尾删除空白:

const { childNodes } = document.getElementById("listItem");
let text = "";
for (const node of childNodes) {
    if (node.nodeType === Node.TEXT_NODE) {
        text += node.nodeValue;
    }
}
text = text.trim();

生活例子:

const {childNodes} = document.getElementById("listItem"); Let text = ""; (childNodes的const节点){ 如果节点。nodeType === Node.TEXT_NODE) { text += node.nodeValue; } } console.log(文本); <李id = "列" > 这是一些文本 <span id="firstSpan">第一个span文本</span> <span id="secondSpan">Second span text</span> . <span id="secondSpan"> 李< / >

有些人会用reduce来表示。我不是一个粉丝,我认为一个简单的循环更清楚,但这种用法确实在每次迭代时更新累加器,所以它实际上并没有滥用reduce:

const { childNodes } = document.getElementById("listItem");
const text = [...childNodes].reduce((text, node) =>
    node.nodeType === Node.TEXT_NODE ? text + node.nodeValue : text
, "").trim();

const {childNodes} = document.getElementById("listItem"); const text =[…childNodes]。Reduce ((text, node) => 节点。nodeType ===节点。TEXT_NODE吗?文本+节点。nodeValue:文本 ”、“).trim (); console.log(文本); <李id = "列" > 这是一些文本 <span id="firstSpan">第一个span文本</span> <span id="secondSpan">Second span text</span> . <span id="secondSpan"> 李< / >

或者不创建临时数组:

const { childNodes } = document.getElementById("listItem");
const text = Array.prototype.reduce.call(childNodes, (text, node) =>
    node.nodeType === Node.TEXT_NODE ? text + node.nodeValue : text
, "").trim();

const {childNodes} = document.getElementById("listItem"); const text = Array.prototype.reduce。call(childNodes, (text, node) => 节点。nodeType ===节点。TEXT_NODE吗?文本+节点。nodeValue:文本 ”、“).trim (); console.log(文本); <李id = "列" > 这是一些文本 <span id="firstSpan">第一个span文本</span> <span id="secondSpan">Second span text</span> . <span id="secondSpan"> 李< / >

其他回答

对我来说,这似乎是一个过度使用jquery的例子。下面将抓取文本,忽略其他节点:

document.getElementById("listItem").childNodes[0];

你需要修剪它,但它能让你在一个简单的线条中得到你想要的。

EDIT

上面将获得文本节点。要得到实际的文本,使用这个:

document.getElementById("listItem").childNodes[0].nodeValue;

我不会为此而使用jQuery,尤其是那些对元素进行不必要克隆的解决方案。您所需要的就是一个简单的循环抓取文本节点。在现代JavaScript中(在撰写本文时,“现代”是一个移动的目标!),并从结果的开头和结尾删除空白:

const { childNodes } = document.getElementById("listItem");
let text = "";
for (const node of childNodes) {
    if (node.nodeType === Node.TEXT_NODE) {
        text += node.nodeValue;
    }
}
text = text.trim();

生活例子:

const {childNodes} = document.getElementById("listItem"); Let text = ""; (childNodes的const节点){ 如果节点。nodeType === Node.TEXT_NODE) { text += node.nodeValue; } } console.log(文本); <李id = "列" > 这是一些文本 <span id="firstSpan">第一个span文本</span> <span id="secondSpan">Second span text</span> . <span id="secondSpan"> 李< / >

有些人会用reduce来表示。我不是一个粉丝,我认为一个简单的循环更清楚,但这种用法确实在每次迭代时更新累加器,所以它实际上并没有滥用reduce:

const { childNodes } = document.getElementById("listItem");
const text = [...childNodes].reduce((text, node) =>
    node.nodeType === Node.TEXT_NODE ? text + node.nodeValue : text
, "").trim();

const {childNodes} = document.getElementById("listItem"); const text =[…childNodes]。Reduce ((text, node) => 节点。nodeType ===节点。TEXT_NODE吗?文本+节点。nodeValue:文本 ”、“).trim (); console.log(文本); <李id = "列" > 这是一些文本 <span id="firstSpan">第一个span文本</span> <span id="secondSpan">Second span text</span> . <span id="secondSpan"> 李< / >

或者不创建临时数组:

const { childNodes } = document.getElementById("listItem");
const text = Array.prototype.reduce.call(childNodes, (text, node) =>
    node.nodeType === Node.TEXT_NODE ? text + node.nodeValue : text
, "").trim();

const {childNodes} = document.getElementById("listItem"); const text = Array.prototype.reduce。call(childNodes, (text, node) => 节点。nodeType ===节点。TEXT_NODE吗?文本+节点。nodeValue:文本 ”、“).trim (); console.log(文本); <李id = "列" > 这是一些文本 <span id="firstSpan">第一个span文本</span> <span id="secondSpan">Second span text</span> . <span id="secondSpan"> 李< / >

它需要是根据需求量身定制的,这取决于你所看到的结构。对于你提供的例子,这是有效的:

$(document).ready(function(){
     var $tmp = $('#listItem').children().remove();
     $('#listItem').text('').append($tmp);
});

演示:http://jquery.nodnod.net/cases/2385/run

但这取决于标记是否与你发布的内容相似。

这对我来说是个好方法

   var text  =  $('#listItem').clone().children().remove().end().text();

我认为这也将是一个很好的解决方案-如果你想获得所有文本节点的内容是选定元素的直接子。

$(selector).contents().filter(function(){ return this.nodeType == 3; }).text();

注意:jQuery文档使用类似的代码来解释内容函数:https://api.jquery.com/contents/

附注:还有一种更难看的方法,但这更深入地展示了事情是如何工作的,并允许在文本节点之间自定义分隔符(也许你想在那里换行)

$(selector).contents().filter(function(){ return this.nodeType == 3; }).map(function() { return this.nodeValue; }).toArray().join("");