如何隐藏子元素在外部动态点击?

时间:2018-08-22 17:10:36

标签: javascript

我可以通过向每个子元素添加以下代码来隐藏子元素:

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

但是如何隐藏子ul元素(在带有for循环或其他功能的情况下)在子ul元素外部单击而不隐藏每个子元素的代码?

在这段代码中,我在单击父li元素时显示了子ul元素

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>

谢谢

2 个答案:

答案 0 :(得分:1)

如果我理解您的问题:用户单击任何子元素,则子状态(隐藏)不应有任何变化。您可以使用以下代码(我假设您仅使用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>

答案 1 :(得分:1)

您可以使用document.querySelectorAll代替定位单个元素 由于要显示子级,因此单击将位于li上,因此再次执行querySelector并选择ul并添加样式。

请注意stopPropagation的使用。body附加了另一个事件,因此,对body的任何单击都会隐藏该子级。 stopPropagation的用途是防止事件从bubling阶段开始同时单击li和单击body。

身体以红色边框

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>