使用纯js获取具有特定类别的clicked元素的下一个元素

时间:2017-10-03 15:11:51

标签: javascript

我试图通过以下方式获取具有特定类的第一个元素,该元素遵循使用纯JS(无JQuery)单击的元素但是获取el.nextSibling不是函数错误。最初我使用的是JQuery parents()。next()但是想用纯JS做这个:



const togglers = document.querySelectorAll('.toggler');
//console.log(togglers);
togglers.forEach(function(el) {
  el.addEventListener('click', function(e) {
    //const content = el.innerHTML;
    //console.log(content);
    el.nextSibling('.folder-content').style.display = 'block';
  })
});

<div class="folder">
  <div class="toggler">Click me 1</div>
  <div class="folder-content" style="display: none">
    Lorem ipsum
  </div>
</div>
<div class="folder">
  <div class="toggler">Click me 2</div>
  <div class="folder-content" style="display: none">
    Lorem ipsum
  </div>
</div>
&#13;
&#13;
&#13;

任何帮助将不胜感激:)

3 个答案:

答案 0 :(得分:5)

nextElement是属性,不是函数,因此您不能使用()。也就是说,使用nextSibling可以为您提供您不想要的空白内容。相反,您可以使用nextElementSibling

el.nextElementSibling.style.display = 'block';

&#13;
&#13;
const togglers = document.querySelectorAll('.toggler');
//console.log(togglers);
togglers.forEach(function(el) {
  el.addEventListener('click', function(e) {
    //const content = el.innerHTML;
    //console.log(content);
    el.nextElementSibling.style.display = 'block';
  })
});
&#13;
<div class="folder">
  <div class="toggler">Click me 1</div>
  <div class="folder-content" style="display: none">
    Lorem ipsum
  </div>
</div>
<div class="folder">
  <div class="toggler">Click me 2</div>
  <div class="folder-content" style="display: none">
    Lorem ipsum
  </div>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

您可以添加while循环来搜索符合条件的第一个nextSibling

编辑正如@ j08691指出的那样,如果您的真实代码只关心元素而不关心其他节点类型,则可以使用nextElementSibling。

&#13;
&#13;
const togglers = document.querySelectorAll('.toggler');
//console.log(togglers);
togglers.forEach(function(el) {
  el.addEventListener('click', function(e) {
    var nextSibling = el.nextSibling;
    while (nextSibling) {
        if (
            nextSibling.nodeType == Node.ELEMENT_NODE
         && nextSibling.classList.contains('folder-content')
        ) {
            nextSibling.style.display = 'block';
            break;
        }
        nextSibling = nextSibling.nextSibling;
    }
  })
});
&#13;
<div class="folder">
  <div class="toggler">Click me 1</div>
  <div>not this</div>
  <div>not this</div>
  <div class="folder-content" style="display: none">
    Lorem ipsum 1!
  </div>
  <div>not this</div>
  <div class="toggler">Click me 1.5</div>
  <div>not this</div>
  <div class="folder-content" style="display: none">
    Lorem ipsum 1.5!
  </div>
  <div>not this</div>
  <div>not this</div>
</div>
<div class="folder">
  <div class="toggler">Click me 2</div>
  <div class="folder-content" style="display: none">
    Lorem ipsum
  </div>
</div>
<div class="folder">
  <div class="toggler">Click me 3</div>
  <div>no folder content here!</div>
</div>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

我正在构建这个答案,而其他人正在进来,为了多样化和整洁的DOM编程,这里是另一种方法来剥离这只猫:

以下是您通过调用单独的函数来执行所请求的初始代码(找到与指定查询字符串匹配的下一个兄弟)

const togglers = document.querySelectorAll('.toggler');

togglers.forEach(function(el, i) {
  el.addEventListener('click', function(e) {

    searchNextSiblings(el, ".folder-content", function(ele) {
      ele.style.display = "block";
    });
  })
});

您会注意到我提供的功能称为searchNextSiblings,它需要三个参数:

  1. 您要搜索的元素。
  2. 您希望找到的元素匹配的查询字符串。
  3. 接收找到的元素的函数,您可以使用它来操作它。
  4. 这是函数本身:

    function searchNextSiblings(ele, q, fn) {
        let flag = false;
        const nodeIterator = document.createNodeIterator(
      ele.parentNode, 
      NodeFilter.SHOW_ELEMENT, 
      function(node) {
            if (ele.isSameNode(node)) flag = true;
            if (!flag) return NodeFilter.FILTER_REJECT;
            else {
                if (node.matches(q)) {
                    flag = false;
                    return NodeFilter.FILTER_ACCEPT
                };
            }
        });
        let currentNode;
        while (currentNode = nodeIterator.nextNode()) {
            fn(currentNode);
        }
    }
    

    以下是带注释的版本:

        function searchNextSiblings(ele, q, fn) {
    // we want to search from the first Element provided
    // to properly search we will set our crawler to begin
    // from its parent node, and when we reach the first Element
    // we will begin searching for the Query String
    // in order to do this we declare a flag to False
    // when we reach the first Element we will set it as True
    // This will let us know when we can search for the Matching Query
    
        let flag = false;
        const nodeIterator = document.createNodeIterator(
          ele.parentNode, //root to search from
          NodeFilter.SHOW_ELEMENT, //set the iterator to search for elements
          function(node) { 
            if (ele.isSameNode(node)) flag = true;
    //if we've found the first Element, set the flag to True
            if (!flag) return NodeFilter.FILTER_REJECT;
    //if the flag is False, continue searching for first Element
            else {
    //if we have found the first Element,
    //we are now searching for the Element that Matches the Query
                if (node.matches(q)) {
    //if we find a matching element
                    flag = false;
    //set the flag to false to stop the search
                    return NodeFilter.FILTER_ACCEPT
    //return the found node
                };
            }
        });
    // the above declares the node iterator
    // but does not start it up
    
        let currentNode;
        while (currentNode = nodeIterator.nextNode()) {
            fn(currentNode);
        }
    //the above "starts up" the nodeIterator
    }
    

    const togglers = document.querySelectorAll('.toggler');
    togglers.forEach(function(el, i) {
    	el.addEventListener('click', function(e) {
    		searchNextSiblings(el, ".folder-content", function(ele) {
    			ele.style.display = "block";
    		});
    	})
    });
    
    function searchNextSiblings(ele, q, fn) {
    	let flag = false;
    	const nodeIterator = document.createNodeIterator(
      ele.parentNode, 
      NodeFilter.SHOW_ELEMENT, 
      function(node) {
    		if (ele.isSameNode(node)) flag = true;
    		if (!flag) return NodeFilter.FILTER_REJECT;
    		else {
    			if (node.matches(q)) {
    				flag = false;
    				return NodeFilter.FILTER_ACCEPT
    			};
    		}
    	});
    	let currentNode;
    	while (currentNode = nodeIterator.nextNode()) {
    		fn(currentNode);
    	}
    }
    <div class="folder">
      <div class="toggler">Click me 1</div>
      <div class="folder-content" style="display: none">
        Lorem ipsum
      </div>
    </div>
    <div class="folder">
      <div class="toggler">Click me 2</div>
      <div class="folder-content" style="display: none">
        Lorem ipsum
      </div>
    </div>