Как скрыть дочерний элемент, щелкнув снаружи динамически?

Я могу скрыть дочерний элемент, добавив каждый дочерний элемент в этот код:

window.addEventListener('mouseup', function(event){
let children = parent[0].children[0]
if (event.target != children && event.target.parentNode != children){
    children.style.display = 'none';
  }
});

Но как можно скрыть щелчок дочернего элемента ul за пределами дочернего элемента ul (с циклом for или чем-то еще), не добавляя этот код для каждого дочернего элемента?

В этом коде я показываю дочерний элемент ul при нажатии на родительский элемент li

var parent = document.querySelectorAll('body > ul > li');

parent[0].addEventListener('click', function () {
  parent[0].children[0].style.display = 'block';
});

parent[1].addEventListener('click', function () {
  parent[1].children[0].style.display = 'block';
});

parent[2].addEventListener('click', function () {
  parent[2].children[0].style.display = 'block';
});

window.addEventListener('mouseup', function(event){
  let children = parent[0].children[0]
	if (event.target != children && event.target.parentNode != children){
        children.style.display = 'none';
    }
});
ul > li > ul {
  display: none;
}

ul, li {
  width: max-content;
}
<ul>
  <li>parent1
    <ul>
      <li>child1</li>
    </ul>
  </li>
  <li>parent2
    <ul>
      <li>child2</li>
    </ul>
  </li>
  <li>parent3
    <ul>
      <li>child3</li>
    </ul>
  </li>
</ul>

Спасибо

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
89
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Если я понимаю вашу проблему: пользователь нажимает на любой из дочерних элементов, в дочернем состоянии не должно быть никаких изменений (скрыть). Вы можете использовать приведенный ниже код (я предполагаю, что вы используете только ES5). Если вы хотите скрыть дочерние элементы по родительскому щелчку, удалите метод isParentClick().

    var parent = document.querySelectorAll('body > ul > li');
    var len = parent.length;
    for(var i=0;i<len;i++){
      	parent[i].addEventListener('click', function (event) {
        if (event.target !== event.currentTarget.children[0].children[0]){
            if (event.currentTarget.children[0].style.display === 'block'){
              event.currentTarget.children[0].style.display = 'none';
            } else {
              event.currentTarget.children[0].style.display = 'block';
            }
         }
            
    	});
      }
    
    window.addEventListener('mouseup', function(event){  
      if (isParentClick()){
      	return false;
      }
      
      if (isChildClick(event)){
      	return false;
      }
      for(var i=0;i<len;i++){
      	parent[i].children[0].style.display = 'none';
      }
    });
    
    function isParentClick(){
      for(var i=0;i<len;i++){
      	if (parent[i] === event.target){
         return true;
        }
      }
      return false;
    }
    
    function isChildClick(event){
      for(var i=0;i<len;i++){
      	if (parent[i].children[0].children[0] === event.target){
         return true;
        }
      }
      return false;
    }
ul > li > ul {
  display: none;
}

ul, li {
  width: max-content;
}
<ul>
  <li>parent1
    <ul>
      <li>child1</li>
    </ul>
  </li>
  <li>parent2
    <ul>
      <li>child2</li>
    </ul>
  </li>
  <li>parent3
    <ul>
      <li>child3</li>
    </ul>
  </li>
</ul>

Но как сделать, чтобы при повторном нажатии родительского <li> скрыть дочерний <ul>. Например, щелкните parent1, покажите child1, а когда снова щелкните parent1, скройте child1. Спасибо

black 23.08.2018 13:29

@GalibHasanov Вы можете проверить состояние отображения chid, щелкнув родительский элемент. Пожалуйста, проверьте обновленный код.

gagan 23.08.2018 15:57

Но теперь я нажимаю на ребенка, а затем его прячу. Как этого избежать?

black 23.08.2018 16:05

Хм. Если мы нажимаем на дочерний элемент, мы также запускаем событие родительского щелчка. Я поставил условие в обновленной кодовой базе. Теперь он должен работать.

gagan 23.08.2018 16:17

Вы можете использовать document.querySelectorAll вместо нацеливания на отдельные элементы Поскольку для отображения дочернего элемента щелчок будет на li, поэтому снова выполните querySelector, выберите ul и добавьте стиль.

Обратите внимание на использование stopPropagation. К body прикреплено еще одно событие, так что любой щелчок по body скроет дочерний элемент. Использование stopPropagation заключается в том, чтобы предотвратить событие из фазы bubling, щелчок по li и щелчок по телу будут происходить одновременно.

Тело окаймлено красным

var parent = document.querySelectorAll('body > ul > li');

parent.forEach(function(item) {
  item.addEventListener('click', function(e) {
    e.stopPropagation()
    
    item.querySelector('ul').style.display = 'block';
  })
  document.body.addEventListener('click', function(e) {
    document.querySelectorAll('.parent').forEach(function(item) {
      item.querySelector('ul').style.display = 'none'
    })
  })
})
ul>li>ul {
  display: none;
}

ul,
li {
  width: max-content;
}

body {
  border: 1px solid red;
}
<ul>
  <li class='parent'>parent1
    <ul>
      <li>child1</li>
    </ul>
  </li>
  <li class='parent'>parent2
    <ul>
      <li>child2</li>
    </ul>
  </li>
  <li class='parent'>parent3
    <ul>
      <li>child3</li>
    </ul>
  </li>
</ul>

Но как сделать, чтобы при повторном нажатии родительского <li> скрыть дочерний <ul>. Например, щелкните parent1, покажите child1, а когда снова щелкните parent1, скройте child1.

black 23.08.2018 12:51

@GalibHasanov взгляните на toggle

brk 23.08.2018 15:22

Я меняю код. Похоже, он работает, но теперь, когда я нажимаю на дочерний элемент, он скрывается. jsfiddle.net/tr2uk9fs/3

black 23.08.2018 15:45

Другие вопросы по теме