Как мне получить родителей определенного элемента?

#javascript

#javascript

Вопрос:

Я пытаюсь получить всех родителей (у которых есть класс «parent») элемента (у которых есть класс «active»), а затем применить к нему стиль. Но, похоже, он не находит те элементы, которые я запрашиваю.

Это HTML-код, который я сейчас использую:

 <ul>
  <li class="parent">
    <ul class="children">
      <li class="active">Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </ul>
  </li>
</ul>
  

И я использую следующий файл Javascript, чтобы применить стиль ко всем родителям с классом «parent» начального элемента с классом «active»:

 function openList() {
  el = document.getElementsByClassName("active");
  while (el.parentNode) {
    el = el.parentNode;
    if (el.className === "parent") {
      el.style.display="block";
    }
  }
}

window.onload = openList();
  

Он ничего не возвращает, ни ошибок, но, похоже, работает.

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

1. el.className === "parent" это проверка, которая завершится неудачей, если этот элемент имеет более одного класса. el.classList очень полезно для этого…

2. window.onload = openList(); <— неверно

3. developer.mozilla.org/en-US/docs/Web/API/Element/closest

4. Возможно, вы захотите el.parentElement.parentElement увидеть, как это 2 узла вверх по дереву. Или вы могли бы сделать el.parentElement.closest("li") , если родительский элемент находится выше по dom.

Ответ №1:

Есть две проблемы с кодом.

  • getElementsByClassName Возврат HTMLCollection элемента списка вы должны получить доступ к его первому элементу с помощью [0]
  • Вы устанавливаете window.onload для return функции openList . Просто не вызывайте функцию, т.е. удалите ()

Примечание: вы объявляете el как глобальную переменную. используйте let var или const для объявления.

 function openList() {
  let el = document.getElementsByClassName("active")[0];
  while (el.parentNode) {
    el = el.parentNode;
    if (el.className === "parent") {
      el.style.display="block";
    }
  }
}

window.onload = openList;  
 <ul>
  <li class="parent">
    <ul class="children">
      <li class="active">Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </ul>
  </li>
</ul>  

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

1. в зависимости от того, насколько велик ваш html, может быть лучшим подходом получить все элементы с классом ‘parent’ и посмотреть, есть ли у них дочерний элемент с классом ‘active’

2. Я не понимаю, как это может быть лучшим подходом, чем этот @jonathanHeindl Также @MaheerAli должен использовать classlist, например element.classList.contains(class);

Ответ №2:

Сначала вы вызываете функцию и присваиваете то, что она возвращает в

querySelector(), closest() и classList были бы лучшим способом справиться с этим

 document.querySelector("li.active")
  .closest(".parent")
    .classList
      .add("open");  
 li.parent {
  display: none;
}

li.parent.open {
  display: block;
}  
 <ul>
  <li class="parent">
    <ul class="children">
      <li class="active">Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </ul>
  </li>
</ul>  

Если существует более одного

 document.querySelectorAll("li.active").forEach(element =>
  element
   .closest(".parent")
    .classList
      .add("open")
)  
 li.parent {
  display: none;
}

li.parent.open {
  display: block;
}  
 <ul>
  <li class="parent">
    <ul class="children">
      <li class="active">Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </ul>
  </li>
</ul>

<ul>
  <li class="parent">
    <ul class="children">
      <li class="active">Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </ul>
  </li>
</ul>  

Ответ №3:

 function openList() {
  
  let el = document.getElementsByClassName("parent");
  Array.prototype.forEach.call(el,(parentNode)=>{
    if(parentNode.getElementsByClassName('active').length>0){
         parentNode.style.display="block";
    }
  });
}

window.onload = openList;  
 <ul>
  <li class="parent">
    <ul class="children">
      <li class="active">Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
    </ul>
  </li>
</ul>  

Я предлагаю этот подход, поскольку он, вероятно, лучше работает во время выполнения