多个div的classList.toggle()

时间:2018-10-16 22:20:49

标签: javascript css

我有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>

3 个答案:

答案 0 :(得分:4)

不是使用类,而是遇到分配多个嵌套类的问题,或者不得不使用复杂的 white 逻辑...

我将使用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-color设置为data-color的{​​{1}} (无)
  • 否则将""设置为预先选择的data-color

答案 1 :(得分:1)

检查元素的classname是否为white。如果不是,则将其类名称设置为white-否则,将其设置为所选颜色。您可以将盒子放在容器中,并使用.container > 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>

答案 2 :(得分:1)

答案

请参阅-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-来维护'state',而是将样式附加到data-属性,并具有另一个基于classList状态设置data-的功能。让您100%确定所做的样式更改将永远不会影响JS功能(QA会爱上您)。但这是本文以外的发展。

在此设置中,我们没有使用id,但是我将它们留在了这里,因为它是重要的最佳实践。此代码很可能会演变成具有侦听器的组件,而不是内联onClick调用。 JavaScript选择器应始终附加到iddata-变量,而不是类。而且,ID应该始终存在,以供质量检查小组在其脚本中使用。您可能会冒险更改类名或将其删除以调整样式,并无意间破坏了JS侦听器。

我切换了参数以传递“事件”而不是元素“ this”。使用JS事件函数的任何人都将事件对象作为第一个参数。您可以根据需要将“ this”作为第二个参数,但是event.target会给您同样的东西。

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

HTML <div data-box-color-is="red">1</div>

JS event.target.dataset.boxColorIs

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

作为代码的改进,您可以删除全局JS var,然后使用<body>将值存储在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/