jQuery:查找包含嵌套 ul 的列表项的文本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1023199/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 10:26:27  来源:igfitidea点击:

jQuery: Find the text of a list item that contains a nested ul

jquery

提问by ScottE

I have the following:

我有以下几点:

<ul id="list">
<li>item1
    <ul>
        <li>sub1</li>
        <li>sub2</li>
    </ul>    
</li>
</ul>

I'd like to respond to a li click event and use the text of the li elsewhere. However, if the click is on an li that contains a nested ul, I of course get the text of all elements.

我想响应 li 单击事件并在其他地方使用 li 的文本。但是,如果单击包含嵌套 ul 的 li,我当然会得到所有元素的文本。

$("#list li").click(function() {
    alert($(this).text());
});

returns item1sub1sub2, as expected.

正如预期的那样,返回 item1sub1sub2。

I can't figure out how to get just 'item1' if the item 1 li is clicked. I tried the following (among other things) with no luck:

如果单击项目 1 li,我无法弄清楚如何仅获得“项目 1”。我尝试了以下(除其他外)但没有运气:

$("#list li").click(function() {
    alert($(this).filter("ul").text());
});

Any ideas?

有任何想法吗?

EDIT

编辑

This is a snippet of an example - it could be multiple levels deep. I also do not want to wrap the list item text in a span or other markup.

这是一个例子的片段 - 它可能是多层次的。我也不想将列表项文本包装在跨度或其他标记中。

采纳答案by ozan

What about this approach? Clone the object, remove the clone's children and thenfind the text content.

这种方法怎么样?克隆对象,删除克隆的子对象,然后找到文本内容。

$("#list li").click(function () {
    alert($(this).clone().children().remove().end().text());
}

Perhaps not the most efficient approach, but it's entirely intuitive, pretty tidy, and you don't have to muck with your html.

也许不是最有效的方法,但它完全直观,非常整洁,而且您不必弄乱您的 html。

回答by Josh

Normal DOM methods allow to access text contents for just one element, rather than jquery:

普通的 DOM 方法只允许访问一个元素的文本内容,而不是 jquery:

$("#list li").click(function() {
    alert($(this)[0].firstChild.textContent)
});

firstChild in this case is the textNode beneath the li element

在这种情况下,firstChild 是 li 元素下方的 textNode

回答by Kobi

you're having a hard time because text()does what it should - returns the text of this and all child elements. The easiest thing to do is to add another tag to every <li>, and use this tag.
For example:

你有困难,因为text()它应该做什么 - 返回这个和所有子元素的文本。最简单的做法是给 each 添加另一个标签<li>,并使用这个标签。
例如:

<ul id="list">
<li><span>item1</span>
    <ul>
        <li><span>sub1</span></li>
        <li><span>sub2</span></li>
    </</ul>    
</li>
</ul>

And then you have a simple selector:

然后你有一个简单的选择器:

$("#list li").click(function() {
   alert($(this).find("span").eq(0).text());
});

or, if possilbe (depending on your style), you may add the event to the span:

或者,如果可能(取决于您的风格),您可以将事件添加到跨度:

$("#list span").click(function() {
   alert($(this).text());
});

If you cannot add these <span>s (as you say) you can use jQuery's .contents() to add them for you, similar to what was done here:

如果您无法添加这些<span>s(如您所说),您可以使用 jQuery.contents() 为您添加它们,类似于此处所做的:

Hide B in <x>A<br/>B</x>

在<x>A<br/>B</x>中隐藏B

回答by John Foster

This checks if the list item has any children and if so it filters out only the text nodes and concatenates the result (in this case it will work for text elements wherever they're put in the li). If you only ever want to check for elements at the start you can avoid the for loop and just work with this.firstChild

这将检查列表项是否有任何子项,如果有,则仅过滤出文本节点并连接结果(在这种情况下,它将适用于放在 li 中的任何文本元素)。如果你只想在开始时检查元素,你可以避免 for 循环,只需使用 this.firstChild

$("#list li").click(function(e) {
    if ($(this).children().length > 0) {
       var text = "";
       for (var i = 0; i < this.childNodes.length; i++) {
           var node = this.childNodes[i];
           if (node.nodeType === 3 && $.trim(node.nodeValue).length > 0) {
                text += $.trim(node.nodeValue);
           }
       }
       alert(text);
    }
    else {
       alert($(this).text());
    }
    e.stopPropagation();
});

回答by davesmiths

Another way to achieve same

实现相同目标的另一种方法

$("#list li").click(function() {
    alert($(this).contents().not('ul,ol').text());
});

回答by artlung

So this mechanism pulls out the html from the child element, replaces the newlines with nothing, and then returns the string only up to the first "<" character. I also added event.stopPropagationto avoid calling the click event bubbling up to the parent.

所以这个机制从子元素中取出 html,用空替换换行符,然后只返回字符串直到第一个 " <" 字符。我还添加event.stopPropagation了避免调用冒泡到父级的点击事件。

<script type="text/javascript">
$("#list li").click(function(event) {
    var sourceHTML = $(this).html().replace(/\n/g,'').replace(/<.*/,'');
    alert(sourceHTML);
    event.stopPropagation();
});
</script>

回答by Ali

I think you need to use the each method. so try the following script:

我认为您需要使用 each 方法。所以试试下面的脚本:

$(document).ready(function() {
        $('ul').each(function() {
            $(this).find('li').click(function() {
                var listItem = this;
                alert($(listItem).text());
            });
        })
    });

with the following markup

带有以下标记

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>