纯Javascript如何选择所有选择器但不是这个

时间:2018-04-16 00:32:41

标签: javascript

如何使用纯JavaScript来选择所有.dummy类但不是THIS? 我搜索了一会儿但找不到我想要的答案。

e.g。如果我点击第一个.dummy div,我想选择所有.dummy div而不是我点击的div。

jQuery的实现方式如下,

var $dummy = $('.dummy');
$dummy.on('click', function(){
    $dummy.not(this).......
});

但我想知道如何通过使用纯javascript来实现它

document.querySelectorAll('.dummy').forEach(function(e, i){
  e.addEventListener('click', function(){
    console.log(document.querySelectorAll('.dummy').not(this)); 
    // WRONG not working, also querySelectorAll('.dummy:not(this)'));
  });
});
<div class="dummy">One</div>
<div class="dummy">Two</div>
<div class="dummy">Three</div>
<div class="dummy">Four</div>

5 个答案:

答案 0 :(得分:5)

您可以使用内置的Array.prototype.filter()功能简单地过滤元素数组,以找到您要查找的内容;但是,document.querySelectorAll返回节点列表对象,而不是数组。

将节点列表转换为数组

棘手的部分是,您首先需要将Node List对象转换为数组,然后才能对其进行过滤。

这可以通过两种方式完成:

  1. ES6方式(Spread Operator)。

    [...document.querySelectorAll('.dummy')];

  2. 前ES6方式(Array.prototype.slice)

    Array.prototype.slice.call(document.querySelectorAll('.dummy'));

  3. 过滤结果

    您已经e存储了对每个虚拟元素的引用,可以在事件侦听器中使用它来过滤掉匹配元素。

    elements.filter(function(element) {
      return element !== e;
    });
    

    完整解决方案

    &#13;
    &#13;
    document.querySelectorAll('.dummy').forEach(function(e, i){
      e.addEventListener('click', function(){
        var elements = [...document.querySelectorAll('.dummy')];
    
        var otherElements = elements.filter(function(element) {
          return element !== e;
        });
        
        console.log(otherElements);
      });
    });
    &#13;
    <div class="dummy">One</div>
    <div class="dummy">Two</div>
    <div class="dummy">Three</div>
    <div class="dummy">Four</div>
    &#13;
    &#13;
    &#13;

答案 1 :(得分:1)

除了已经给出的答案(它们非常有用但不一定等效),如果元素有其他识别属性,你可以这样使用:

document.querySelectorAll('.dummy').forEach(function(e, i){
  e.addEventListener('click', function(event){
    console.log(document.querySelectorAll('.dummy:not([myattr="' + event.target.getAttribute("myattr") + '"])'));
  });
});
<div class="dummy" myattr="1">One</div>
<div class="dummy" myattr="2">Two</div>
<div class="dummy" myattr="3">Three</div>
<div class="dummy" myattr="4">Four</div>

答案 2 :(得分:1)

每个元素都在this.previousSiblingthis.nextSibling上附加了LinkedList的兄弟姐妹中。虽然您可以在再次调用querySelectorAll后进行过滤,但我想显示一个您不需要再次调用查询的选项。此外,您可以确定这些实际上是兄弟姐妹,而不是页面上的其他.dummy(您也可以通过为querySelectorAll设置正确的上下文来实现此目的)

&#13;
&#13;
/**
 * @param acc  {Array}  An array to push onto
 * @param el   {Node}   The element to cycle over
 */
function getPrevSiblings(acc, el) {
  if(el.previousSibling) {
  	// Ignores #text elements
  	if(el.previousSibling.nodeName !== "#text" ) {
    	acc.push(el.previousSibling);
    }

    return getPrevSiblings(acc, el.previousSibling)
  }
  return acc;
}

/**
 * @param acc  {Array}  An array to push onto
 * @param el   {Node}   The element to cycle over
 */
function getNextSiblings(acc, el) {
  if(el.nextSibling) {
  	// Ignores #text elements
  	if(el.previousSibling.nodeName !== "#text" ) {
    	acc.push(el.nextSibling);
    }
    return getNextSiblings(acc, el.nextSibling)
  }
  return acc;
}

document.querySelectorAll('.dummy').forEach(function(e, i){
  e.addEventListener('click', function(){
    var prev = getPrevSiblings([], this)
    var next = getNextSiblings([], this)
    var allElsForLogging = [].concat(prev, next);
    console.log(allElsForLogging); 
  });
});
&#13;
<div>
  <div class="dummy">One</div>
  <div class="dummy">Two</div>
  <div class="dummy">Three</div>
  <div class="dummy">Four</div>
</div>
&#13;
&#13;
&#13;

答案 3 :(得分:1)

扩展内置对象&#34; NodeList&#34;如下:

&#13;
&#13;
//Extends NodeList
NodeList.prototype.not = function ( cssSelectorOrNodeOrNodeList ) {
    //Change object name(constructor.name) to "NodeList" from "Array" in console window
    let list = ( () => { class NodeList extends Array {} return new NodeList(); } )(), excludes;

    if ( typeof cssSelectorOrNodeOrNodeList === "string" ) excludes = document.querySelectorAll( cssSelectorOrNodeOrNodeList );
    else if ( cssSelectorOrNodeOrNodeList instanceof NodeList ) excludes = cssSelectorOrNodeOrNodeList;
    else if ( cssSelectorOrNodeOrNodeList instanceof Node ) excludes = [ cssSelectorOrNodeOrNodeList ];
    
    if ( excludes === undefined || !excludes.length ) return this;

    for ( const node of this ) {
        let flag = true;
        for ( const compare of excludes ) {
            if ( node === compare ) {
                flag = false;
                break;
            }
        }
        if ( flag ) list.push( node );
    }
    Object.setPrototypeOf( list, NodeList.prototype );

    return list;
};

//Object information
{
    let test = document.childNodes.not( document.body );
    console.log( test.constructor.name ); //NodeList
    console.log( test.constructor === NodeList ); //true
    console.log( test instanceof NodeList ); //true
    console.log( test instanceof Array ); //false
    console.dir( test ); //NodeList .... not Array ....;
}

//Your test code

document.querySelectorAll('.dummy').forEach(function(e, i){
  e.addEventListener('click', function(){
    console.log(document.querySelectorAll('.dummy').not(this)); 
    // WRONG not working, also querySelectorAll('.dummy:not(this)'));
  });
});
&#13;
<div class="dummy">One</div>
<div class="dummy">Two</div>
<div class="dummy">Three</div>
<div class="dummy">Four</div>
&#13;
&#13;
&#13;

您可以像刚写的那样使用它。

答案 4 :(得分:0)

您可以循环回复元素并使用if

document.querySelectorAll('.dummy').forEach(function(e, i){
  e.addEventListener('click', function(){
    console.log(document.querySelectorAll('.dummy').forEach((e) => {
      if (e !== this) {
        e.style.color = 'red';
      }
    }));
  });
});
<div class="dummy">One</div>
<div class="dummy">Two</div>
<div class="dummy">Three</div>
<div class="dummy">Four</div>