Используйте .find(), чтобы получить всех потомков элемента, но не их потомков

#javascript #jquery

#javascript #jquery

Вопрос:

У меня есть некоторый html, где элементы вложены для создания эффекта аккордеона. Что-то похожее на:

 <span class="container">
    <div class="item">1</div>
    <span class="container">
        <div class="item">1.a</div>
        <span class="container">
            <div class="item">1.a.1</div>
        </span>
    </span>
</span>
  

Мне нужно использовать $('.container').find('.item').each() для создания иерархии, в которой 1.a становится дочерним элементом 1, а 1.a.1 становится дочерним элементом 1.a. Проблема, с которой я сталкиваюсь, заключается в том, что 1.a.1 также становится дочерним элементом 1, потому что 1.a.1 является потомком 1.

Теоретически также может быть 1.b или 1.c и т.д. поэтому мне нужно найти всех потомков, а не только первого, но я не хочу находить потомков потомков.

Есть ли простой способ jQuery сделать это?

.children() не работает для моего конкретного случая, потому что в реальном HTML, в котором я нахожусь, больше вложенных контейнеров и еще много чего.

Комментарии:

1. Вы можете использовать children('.item') или find('> .item') , однако ваш первый селектор будет возвращать все контейнеры, включая вложенные. Таким образом, при отключении такого глобального селектора вы все равно будете возвращать все элементы.

2. Вы могли $('.container').first() бы получить только верхний контейнер, прежде чем получать только его вложенные элементы.

3. @Taplar Я должен был упомянуть об этом, но причина, по которой я использую .find() вместо .children(), заключается в том, что в моем HTML элементы .item не являются прямыми дочерними элементами элементов .container . Я написал макет HTML, поэтому я не вставлял 50 строк, которые, как я ошибочно полагал, были неактуальными.

4. Затем вам нужно будет выбрать конкретный контейнер, найти вложенные элементы, а затем отфильтровать те, чей ближайший контейнер не является нужным контейнером.

5. Вы ищете что-то в строках этого ?

Ответ №1:

Я написал функциональность здесь. Идея в том, что вы ищете всех потомков с item классом. Затем вы удаляете все те элементы из списка, которые имеют предка с item классом. Этот предок все равно должен быть потомком контейнера (или начальной точки вашего элемента).

 var container = $('.container');
var descendants = container.find('.item');
var res = [];
descendants.each(function() {
    let parents = $(this).parents();
    for (let i = 0; i < parents.length; i  ) {
        //console.log('p: '   $(parents[i]).text());
        if (container.html() == $(parents[i]).html()) {
            //no ancestors with the `item` class found, this is a good one.
            res.push($(this));
            break;
        }
        if ($(parents[i]).hasClass('item')) {
            //if an ancestor with the same class has been found
            //it cannot be kept
            break;
        }
    }
});
console.log(descendants);
console.log(res);
  

Я создал скрипку для тестирования

Комментарии:

1. $(parents[i]) является анти-шаблоном. Вы удаляете элемент из стека результатов jQuery, а затем создаете новый объект jQuery только с одним элементом. Используйте .eq(i) , чтобы избежать этого.

2. Также вместо того, чтобы создавать скрипку вне сайта, чтобы показывать рабочий код, создайте исполняемый фрагмент на сайте .