Получить ближайшие дочерние элементы

103
24 сентября 2021, 07:30

Есть некая разметка:

<div class='a' id='parent-1'>
    <div class='b' id='child-1'></div>
    <div class='c'>
        <div class='b' id='child-2'></div>
    </div>
    <div class='b' id='child-3'></div>
    <div class='a' id='parent-2'>
        <div class='b' id='child-4'></div>
        <div class='b' id='child-5'></div>
    </div>
</div>

Необходимо получить ближайшие дочерние элементы .b родителя .a.

Например, для родителя #parent-2 должны быть получены #child-4 и #child-5, а для родителя #parent-1 только #child-1, #child-2 и #child-3, исключая дочерние элементы вложенного родителя.

При этом вложенность элементов может быть любой глубины.

Желательна реализация на чистом JavaScript.

Моя текущая реализация на jQuery (Полагаю что есть решению лучше):

const A = $('.a#parent-1');
$(A).find('.b').filter((_, e) => $(e).closest('.a').is(A));
Answer 1

Можно попробовать сделать так. Создаёт результирующий объект с ключами в качестве id родителя (с любой вложенностью). Ну это на JS, без JQuery:

UPD дополнил код, согласно комментам

let aCont = document.querySelectorAll('.a'); 
let childItems = {}; 
[...aCont].forEach(items => { 
  childItems[items.id] = [...items.children].filter(item => { 
    return item.id.indexOf('parent') === -1; 
  }); 
}); 
 
console.log(childItems);
<div class='a' id='parent-1'> 
    <div class='b' id='child-1'></div> 
    <div class='b' id='child-2'></div> 
    <div class='b' id='child-3'></div> 
    <div class='a' id='parent-2'> 
        <div class='b' id='child-4'></div> 
        <div class='b' id='child-5'></div> 
    </div> 
</div>

let aCont = document.querySelectorAll('.a'); 
let childItems = {}; 
[...aCont].forEach(items => { 
  childItems[items.id] = getChildNodes([...items.children]); 
}); 
 
console.log(childItems); 
 
function getChildNodes(parentItem) { 
  let result = []; 
  parentItem.forEach(item => { 
    if (item.id.indexOf('parent') !== -1) return; 
    if (!item.children.length) { 
      if (item.id.indexOf('child') !== -1) { 
        result.push(item); 
      }  
      return; 
    } 
    result = result.concat(getChildNodes([...item.children])) 
  }); 
  return result; 
}
<div class='a' id='parent-1'> 
    <div class='b' id='child-1'></div> 
    <div class='c'> 
        <div class='b' id='child-2'></div> 
    </div> 
    <div class='b' id='child-3'></div> 
    <div class='a' id='parent-2'> 
        <div class='b' id='child-4'></div> 
        <div class='b' id='child-5'></div> 
    </div> 
</div>

Answer 2

Похоже что сам нашел решение

function getNearestChildrenList(parentId) { 
    return [...document.querySelectorAll('.b')].filter(b => (b.closest('.a').id === parentId)); 
} 
 
console.log(getNearestChildrenList('parent-1'));
<div class='a' id='parent-1'> 
    <div class='b' id='child-1'></div> 
    <div class='c'> 
        <div class='b' id='child-2'></div> 
    </div> 
    <div class='b' id='child-3'></div> 
    <div class='a' id='parent-2'> 
        <div class='b' id='child-4'></div> 
        <div class='b' id='child-5'></div> 
    </div> 
</div>

READ ALSO
переписать jQuery решение на чистый JS

переписать jQuery решение на чистый JS

Есть такое решение на jQuery:

104
Не распознается значение Vue

Не распознается значение Vue

Почему в цикле когда я задаю to="itemhref" значение item

84