【问题标题】:classList.toggle() for multiple divsclassList.toggle() 用于多个 div
【发布时间】:2018-10-16 22:20:48
【问题描述】:

我有 3 个 div 作为颜色可供选择,还有 3 个空白 div。我想让用户能够:

(1) 点击一个彩色的 div,然后点击一个空白的 div,然后空白的 div 被着色为用户选择的颜色。而且代码似乎可以工作。

(2) 我希望用户能够再次单击彩色空白 div 并使其变为白色。而且代码似乎可以工作。

问题是,如果空白 div 是彩色的,而用户选择另一种颜色并再次单击彩色空白 div,则会将新的颜色类添加到 div 中,事情变得不可预测。可以打开控制台,跟踪空白div类的乱七八糟的变化。

我该如何解决这个问题?我只希望空白 div 在两个类之间切换。

var chosenColor;
function pickColor(arg){
  chosenColor=arg.id;
}

function draw(id){
  document.getElementById(id).classList.toggle("white");
  document.getElementById(id).classList.toggle(chosenColor);
}
.box{
  width: 100px;
  height: 100px;
  border: 1px solid black;
  display: inline-block;
  
}

.red{background: red}
.blue{background: blue;}
.yellow{background: yellow;}
.white{background: white;}
<html>
  <body>
    <div class="box red" id="red" onclick="pickColor(this)">1</div>
    <div class="box blue" id="blue" onclick="pickColor(this)">2</div>
    <div class="box yellow" id="yellow" onclick="pickColor(this)">3</div>
    <br><br>
    <div class="box white" id="4" onclick="draw(4)">4</div>
    <div class="box white" id="5" onclick="draw(5)">5</div>
    <div class="box white" id="6" onclick="draw(6)">6</div>
  </body>
</html>

【问题讨论】:

  • 所以你想让彩色的空白 div 再次变白,即使用户在两者之间选择了另一种颜色?
  • 是的,某些性能的答案正是我想要的

标签: javascript css


【解决方案1】:

而不是使用类并遇到分配多个嵌套类或必须使用复杂的白色逻辑的问题......

我会使用data-* 属性:

var chosenColor;

function pick(el) {
  chosenColor = el.dataset.color;
}

function draw(el) {
  el.dataset.color = el.dataset.color ? "" : chosenColor;
}
body { background: #eee; }

.box {
  width: 100px;
  height: 100px;
  border: 1px solid black;
  display: inline-block;
  background: white;         /* BY DEFAULT !!! */
}

[data-color=red]    { background: red; }
[data-color=blue]   { background: blue; }
[data-color=yellow] { background: yellow; }
<div class="box" onclick="pick(this)" data-color="red">1</div>
<div class="box" onclick="pick(this)" data-color="blue">2</div>
<div class="box" onclick="pick(this)" data-color="yellow">3</div>
<br><br>
<div class="box" onclick="draw(this)">4</div>
<div class="box" onclick="draw(this)">5</div>
<div class="box" onclick="draw(this)">6</div>

三元el.dataset.color = el.dataset.color ? "" : chosenColor;的作用是:

  • 如果元素已经有任何data-colordata-color 设置为"" (什么都没有)
  • 否则将data-color 设置为预选的chosenColor

【讨论】:

    【解决方案2】:

    检查元素的classname 是否为white。如果不是,将其类名设置为white - 否则,将其设置为所选颜色。您可以将盒子放在容器中并使用.container &gt; div 选择器,无需为盒子提供.box 类。此外,在侦听器中,this 将引用单击的元素 - 如果您已经引用了该元素,则无需使用 getElementById

    var chosenColor;
    
    function pickColor(arg) {
      chosenColor = arg.id;
    }
    
    function draw(element, id) {
      if (element.className !== 'white') element.className = 'white';
      else element.className = chosenColor;
    }
    .container > div {
      width: 100px;
      height: 100px;
      border: 1px solid black;
      display: inline-block;
    }
    
    .red {
      background: red
    }
    
    .blue {
      background: blue;
    }
    
    .yellow {
      background: yellow;
    }
    
    .white {
      background: white;
    }
    <div class="container">
      <div class="red" id="red" onclick="pickColor(this)">1</div>
      <div class="blue" id="blue" onclick="pickColor(this)">2</div>
      <div class="yellow" id="yellow" onclick="pickColor(this)">3</div>
      <br><br>
      <div class="white" id="4" onclick="draw(this, 4)">4</div>
      <div class="white" id="5" onclick="draw(this, 5)">5</div>
      <div class="white" id="6" onclick="draw(this, 6)">6</div>
    </div>

    【讨论】:

      【解决方案3】:

      回答

      见 - https://codepen.io/stephanieschellin/pen/xyYxrj/(注释代码)

      或者...

      var activeColor
      
      function setPickerColor(event) {
        activeColor = event.target.dataset.boxColorIs
      }
      
      function setThisBoxColor(event) {
        let element = event.target
        let the_existing_color_of_this_box = element.dataset.boxColorIs
      
        if (the_existing_color_of_this_box == activeColor) {
          delete element.dataset.boxColorIs
        } else {
          element.dataset.boxColorIs = activeColor
        }
      }
      .box {
        width: 100px;
        height: 100px;
        border: 1px solid black;
        display: inline-block;
        background: white;
      }
      
      [data-box-color-is="red"] {
        background: red
      }
      
      [data-box-color-is="blue"] {
        background: blue;
      }
      
      [data-box-color-is="yellow"] {
        background: yellow;
      }
      <html>
      
      <body>
        <div id="box-1" class="box" data-box-color-is="red" onclick="setPickerColor(event)">1</div>
        <div id="box-2" class="box" data-box-color-is="blue" onclick="setPickerColor(event)">2</div>
        <div id="box-3" class="box" data-box-color-is="yellow" onclick="setPickerColor(event)">3</div>
        <br>
        <br>
        <div id="box-4" class="box" onclick="setThisBoxColor(event)">4</div>
        <div id="box-5" class="box" onclick="setThisBoxColor(event)">5</div>
        <div id="box-6" class="box" onclick="setThisBoxColor(event)">6</div>
      </body>
      
      </html>

      使用data- 属性,您可以将JavaScript 功能关注点与CSS 类分离。这简化了您的逻辑,但最重要的是,它允许设计您的应用程序的人员独立于添加 JS 功能的人员工作。当您的团队使用 BEM 或 OOCSS 模式时,这种解耦变得非常重要。

      理想情况下,不是将样式附加到data- 属性,而是使用data- 维护“状态”,并拥有另一个基于data- 状态设置classList 的函数。让您 100% 确定您所做的样式更改永远不会影响 JS 功能(QA 会喜欢您的)。但这是超越这篇文章的演变。

      通过此设置,我们没有使用id,但我将它们留在了其中,因为它是一个重要的最佳实践。这段代码很可能会演变成一个带有侦听器的组件,而不是内联 onClick 调用。 JavaScript 选择器应始终附加到 iddata- 变量,而不是类。此外,id 应该始终存在,供 QA 团队在他们的脚本中使用。您冒着有人更改类名或删除它以调整样式并无意中破坏您的 JS 侦听器的风险。

      我切换了参数以传递“事件”而不是元素“this”。任何使用您的 JS 事件函数的人都会期望事件对象作为第一个参数。如果你愿意,你可以传递 'this' 作为第二个参数,但是 event.target 会给你同样的东西。

      另外需要注意的是声明data- 变量和从JS 调用它之间的语法变化。

      HTML &lt;div data-box-color-is="red"&gt;1&lt;/div&gt;

      JS event.target.dataset.boxColorIs

      无论您如何格式化数据属性名称,在 JS 中引用它时,它总是会被解析为 camelCase ...data-box_color--IS 仍将变为 ...dataset.boxColorIs

      此外,作为对代码的改进,您可以删除全局 JS 变量并将值存储在 &lt;body&gt; 或使用 data- 的页面上的其他元素上。这将为您提供单一的事实来源或“状态”,多个特征/组件可以参考,而不会弄乱全局空间。

      进一步阅读

      https://css-tricks.com/bem-101/

      https://en.bem.info/

      https://philipwalton.com/articles/side-effects-in-css/

      https://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/

      https://philipwalton.com/articles/decoupling-html-css-and-javascript/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-24
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多