如果我有这样的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"> 李< / >

其他回答

我建议使用createTreeWalker来查找所有没有附加到html元素的文本元素(这个函数可以用来扩展jQuery):

function textNodesOnlyUnder(el) { var resultSet = []; var n = null; var treeWalker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, function (node) { if (node.parentNode.id == el.id && node.textContent.trim().length != 0) { return NodeFilter.FILTER_ACCEPT; } return NodeFilter.FILTER_SKIP; }, false); while (n = treeWalker.nextNode()) { resultSet.push(n); } return resultSet; } window.onload = function() { var ele = document.getElementById('listItem'); var textNodesOnly = textNodesOnlyUnder(ele); var resultingText = textNodesOnly.map(function(val, index, arr) { return 'Text element N. ' + index + ' --> ' + val.textContent.trim(); }).join('\n'); document.getElementById('txtArea').value = resultingText; } <li id="listItem"> This is some text <span id="firstSpan">First span text</span> <span id="secondSpan">Second span text</span> </li> <textarea id="txtArea" style="width: 400px;height: 200px;"></textarea>

jQuery.fn.ownText = function () {
    return $(this).contents().filter(function () {
        return this.nodeType === Node.TEXT_NODE;
    }).text();
};

就像问题一样,我试图提取文本,以便对文本进行一些正则表达式替换,但在我的内部元素(即:< I >, <div>, <span>等)也被删除的地方出现问题。

下面的代码似乎工作得很好,解决了我的所有问题。

它使用这里提供的一些答案,但特别地,只会在元素为nodeType === 3时替换文本。

$(el).contents().each(function() { 
  console.log(" > Content: %s [%s]", this, (this.nodeType === 3));

  if (this.nodeType === 3) {
    var text = this.textContent;
    console.log(" > Old   : '%s'", text);

    regex = new RegExp("\\[\\[" + rule + "\\.val\\]\\]", "g");
    text = text.replace(regex, value);

    regex = new RegExp("\\[\\[" + rule + "\\.act\\]\\]", "g");
    text = text.replace(regex, actual);

    console.log(" > New   : '%s'", text);
    this.textContent = text;
  }
});

上面所做的是遍历给定el的所有元素(它是通过$("div.my-class[name='some-name']"获得的);对于每个内部元素,它基本上都会忽略它们。对于文本的每个部分(由if (this。nodeType === 3),它将只对这些元素应用regex替换。

这。textContent = text部分只是替换替换的文本,在我的情况下,我正在寻找像[[min.val]], [[max.]]这样的标记。val]]等。

这段简短的代码摘录将帮助任何人试图做什么问题是问…再多一点。

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

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

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

现场演示

<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>