如果我有这样的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是预先编写的。


当前回答

我喜欢这个基于clone()方法的可重用实现,它只获取父元素中的文本。

为方便参考而提供的代码:

$("#foo")
    .clone()    //clone the element
    .children() //select all the children
    .remove()   //remove all the children
    .end()  //again go back to selected element
    .text();

其他回答

在2022年获取一个元素中的所有文本而没有任何子元素中的文本似乎仍然不是简单的事情。 但是不需要jQuery。

获取所有原始文本节点(s)内容:

const getElementTextWithoutChildElements = (el) =>
  Array.from(el.childNodes)               // iterator to array
    .filter(node => node.nodeType === 3)  // only text nodes
    .map(node => node.textContent)        // get text
    .join('')                             // stick together
;

或者类似的,使用reduce:

const getElementTextWithoutChildElements = (el) =>
  [].reduce.call(
    el.childNodes, 
    (a, b) => a + (b.nodeType === 3 ? b.textContent : ''),
    ''
  );

应该这样做:

<div>
  you get this
  <b>not this</b>
  you get this   too
</div>

将返回:


  you get this

  you get this   too

元素之间的空白可能很棘手,建议使用.trim()和/或规范化所有空白。 对于调试和记录快速识别元素,我发现这通常是足够的:

getElementTextWithoutChildElements(...).replace(/\s+/g, ' ').trim();
// 'you get this you get this too'

尽管您可能希望以不同的方式调整空白,但可以在reduce()函数本身中处理每个节点的空白。

例如,每个节点的空格处理:

const getElementTextWithoutChildElements_2 = (el) =>
  Array.from(el.childNodes)
    .filter(node => node.nodeType === 3)
    .map(node => node.textContent.trim()) // added .trim()
    .join(',')                            // added ','
;

以上内容的快速测试:

document.body.innerHTML = `
  you get this
  <b>not this</b>
  you get this   too
`;
// '\n  you get this\n  <b>not this</b>\n  you get this   too\n'

getElementTextWithoutChildElements(document.body);
// '\n  you get this\n  \n  you get this   too\n'

getElementTextWithoutChildElements(document.body).replace(/\s+/g, ' ').trim();
// 'you get this you get this too'

getElementTextWithoutChildElements_2(document.body);
// 'you get this,you get this   too'

这对我来说是个好方法

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

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

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

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

EDIT

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

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

现场演示

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

<input id="input" style="width: 300px; margin-top: 10px;">

    <script type="text/javascript">
$("#input").val($("#listItem").clone().find("span").remove().end().text().trim());
    //use .trim() to remove any white space
    </script>

试试这个:

$('#listItem').not($('#listItem').children()).text()