使用jQuery从包装集合中收集所有文本节点,用空格分隔

Bun*_*gle 9 javascript jquery dom traversal

我正在寻找一种方法来收集jQuery包装集中的所有文本,但我需要在它们之间没有文本节点的兄弟节点之间创建空格.

例如,考虑这个HTML:

<div>
  <ul>
    <li>List item #1.</li><li>List item #2.</li><li>List item #3.</li>
  </ul>
</div>
Run Code Online (Sandbox Code Playgroud)

如果我只是使用jQuery的text()方法来收集文本内容<div>,就像这样:

var $div = $('div'), text = $div.text().trim();

alert(text);
Run Code Online (Sandbox Code Playgroud)

产生以下文字:

列表项#1.列表项#2.列表项#3.

因为每个<li>元素之间没有空格.我真正想要的是这个(注意每个句子之间的单一空格):

列出项目#1.列出项目#3.列出项目#3.

这告诉我,我需要遍历包装集中的DOM节点,将每个文本附加到字符串,然后是空格.我尝试了以下代码:

var $div = $('div'), text = '';

$div.find('*').each(function() {
  text += $(this).text().trim() + ' ';
});

alert(text);
Run Code Online (Sandbox Code Playgroud)

但这产生了以下文字:

这是列表项#1.这是列表项#2.这是列表项#3.这是列表项#1.这是列表项#2.这是列表项目#3.

我假设这是因为我正在迭代每个后代<div>并附加文本,所以我在两个子节点<ul>和每个<li>子节点中获取文本节点,从而导致重复的文本.

我想我可能会找到/编写一个简单的JavaScript函数来递归遍历包装集的DOM,收集和附加文本节点 - 但是有一种更简单的方法来使用jQuery吗?跨浏览器的一致性非常重要.

谢谢你的帮助!

bob*_*nce 7

jQuery主要处理元素,它的文本节点功能相对较弱.你可以得到所有孩子的列表contents(),但是你仍然需要检查它们的类型,所以这与使用普通DOM完全没什么不同childNodes.没有方法可以递归地获取文本节点,因此您必须自己编写一些内容,例如.就像是:

function collectTextNodes(element, texts) {
    for (var child= element.firstChild; child!==null; child= child.nextSibling) {
        if (child.nodeType===3)
            texts.push(child);
        else if (child.nodeType===1)
            collectTextNodes(child, texts);
    }
}
function getTextWithSpaces(element) {
    var texts= [];
    collectTextNodes(element, texts);
    for (var i= texts.length; i-->0;)
        texts[i]= texts[i].data;
    return texts.join(' ');
}
Run Code Online (Sandbox Code Playgroud)