【问题标题】:remove styles from all nodelist element and add only to clicked element Vanilla JS从所有节点列表元素中删除样式并仅添加到单击的元素 Vanilla JS
【发布时间】:2020-08-28 04:34:23
【问题描述】:

我有多个 div,当单击它们时会添加一个边框并将它们放大一点。我正在使用 foreach 遍历所有元素,单击时我删除了每个元素的边框和缩放属性,但单击的元素除外,我在其中添加了边框和缩放。 我的代码完全合乎逻辑并且应该可以工作,但由于某种原因我似乎无法理解,它只将样式应用于单击的元素,而不是从其余元素中删除(就像我的代码所说的那样)。

JS

    document.querySelectorAll('.projcolorpick div').forEach(el => {
            el.onclick = (e) => {
                el.style.border = "none"
                el.style.transform  = "scale(1)"
                e.target.style.border = "2px solid #fff"
                e.target.style.transform = "scale(1.2)" 
                projcolor = e.target.style.background   
            }
        }) 
     } 

【问题讨论】:

  • 您正在为每个元素添加一个单独的事件侦听器。监听器触发了单击的 el 上的 annon 函数...我看不到任何关于更改每个事件监听器之外的元素的比例...如果我理解正确的话。
  • 那么每次我点击一个元素时如何删除所有其他元素的样式?

标签: javascript loops foreach nodelist


【解决方案1】:

试试这样的东西......每个元素都需要一个 id 属性才能工作(过滤器部分 - 如果有一个独特的属性......)

    const list = Array.from(document.querySelectorAll('.projcolorpick div'));
    list.forEach(el => {
            el.addEventListener('click', (e) => {
                //code that affects the element you click on
                el.style.border = "2px solid #fff"
                el.style.transform = "scale(1.2)" 
                projcolor = e.target.style.background;
                list.filter(x=>x.id!=el.id).forEach(otherEl=>{
                    //code that affects the other elements you didn't click on
                    otherEl.style.border = "none"
                    otherEl.style.transform  = "scale(1)"
                });
            });
        }); 
     
    ```
edit:
fixed some typos.

【讨论】:

  • 我的每个“.projcolorpick div”都有一个独特的数据属性,我如何使用这些而不是 id?
  • 在过滤器中,而不是每个 x 和 el 的 .id。对于 x 和 el,它是 .getAttribute('yourAttribute')
【解决方案2】:

forEach 仅适用于 Arrays,除非您另有配置。

querySelectorAll 不返回数组,而是返回类数组对象(NodeLists)

要允许循环遍历NodeLists,请添加以下代码:

if (window.NodeList && !NodeList.prototype.forEach) { 
    NodeList.prototype.forEach = Array.prototype.forEach;
}


var nL = document.querySelectorAll('*');

console.log(nL instanceof NodeList); // true

【讨论】:

  • Array.from() 是我解决这个问题的方法......并不是说我正在敲这种漂亮的方法。
  • 我在任何地方都使用我自己的自定义 foreach 函数,哈哈。原生 forEach 很好,但有时您仍想跳出循环。想看吗? :-)
  • @Kithraya, Array.every() 是一种已经存在的.forEach() 方法,可以选择在您返回false 后立即退出(如果您想返回,请使用Array.some() true 代替)。
【解决方案3】:

您实际上并不需要每个 div 上的 id 属性,我会提倡使用类分配而不是更改它们的各个属性。您可以像c==ev.target 一样将实际的 DOM 元素相互比较,如下面的代码所示:

// === populate the page first ... ============================= START =
const cont=document.getElementById('container');
cont.innerHTML=
[...Array(3)].map(cp=>'<div class="projcolorpick">'+
  [...Array(8)].map(d=>{
    let hsl= "hsl("+Math.floor(Math.random()*360)+",100%,80%)";
    return '  <div style="background-color:'+hsl+'">'+hsl+'</div>'}).join('\n')
  +'</div>').join('\n');
// === populate the page first ... =============================== END =
  
// now, do the action:
cont.onclick=ev=>{
  if (   ev.target.parentNode.classList.contains('projcolorpick')
      && ev.target.tagName=='DIV'){
    [...ev.target.parentNode.children].forEach(c=>c.classList.toggle('selected',c==ev.target));
    ev.target.parentNode.style.backgroundColor=ev.target.textContent;
  }
}
.projcolorpick {border: 2px solid #888}
.selected {border: 2px solid #fff; transform:scale(1.2);}
div {margin:6px; padding:4px}
.projcolorpick div {width:200px; height:20px}
&lt;div id="container"&gt;&lt;/div&gt;

动作发生在这里:

cont.onclick=ev=>{
      if (   ev.target.parentNode.classList.contains('projcolorpick')
          && ev.target.tagName=='DIV'){
        [...ev.target.parentNode.children].forEach(c=>c.classList.toggle('selected',c==ev.target));
        ev.target.parentNode.style.backgroundColor=ev.target.textContent;
      }
    }

我使用委托事件附件到父 .container div。第一个if 语句确保只处理对.projcolorpick&gt;div 元素的点击。

如果您想在它们之间包含多于一代,则需要使用 ev.target.closest('.projcolorpick') 之类的东西...

现在,在 if 块内发生了两件事:

  1. 在ev.target.parentNode.children 中的所有DOM 元素上使用toggle(),“selected”类是
    • 分配或
    • 已删除。
  2. 在单击的 div 中找到的文本将作为 background-color 应用于父 .projcolorpick 容器。

【讨论】:

    猜你喜欢
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-24
    • 2020-05-07
    • 1970-01-01
    相关资源
    最近更新 更多