1
\$\begingroup\$

I recently started delving into Vue.js, and decided to try my hand at some custom class/style bindings, so I made a small app that's supposed to cycle through each "light" of a stoplight (red, yellow, green, red, etc.).

My Vue instance has a data property count, which is initially set to 0, and I also have a setInterval callout that is to increments the count every one second.

Each "light" in the stoplight has a Bootstrap button class associated with it (btn-danger for red, btn-warning for yellow, and btn-success for green), and each class becomes "active" based on some modulus arithmetic against my Vue instance's count.

I'm wondering if perhaps I could be handling the change in these classes more efficiently, but am not sure what could be done.

Here is my current code:

var app = new Vue({
  el: '#app',
  data: {
    count: 0,
    styleObject: {
      display: 'block',
      width: '30px',
      margin: '0',
      borderRadius: '50px',
      border: '1px solid black'
    }
  }
});

setInterval(function() {
  app.count = app.count + 1;
}, 1000);
#light {
  background-color: yellow;
  display: inline-block;
  border: 2px solid black;
  margin: 10px;
  padding: 5px;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="app">
  <div id='light'>
    <input type='button' id='red' :class='["btn", (count % 3 === 0) && "btn-danger"]' :style='styleObject' />
    <br />
    <input type='button' id='yellow' :class='["btn", (count % 3 === 1) && "btn-warning"]' :style='styleObject' />
    <br />
    <input type='button' id='green' :class='["btn", (count % 3 === 2) && "btn-success"]' :style='styleObject' />
  </div>
</div>

\$\endgroup\$
1
\$\begingroup\$

You could use the Object Syntax to specify the class bindings instead of the Array Syntax:

<input type='button' id='red' :class='{"btn": true, "btn-danger": (count % 3 === 0)}'  />

That "btn": true is okay but a little annoying. Luckily "it’s also possible to use the object syntax inside array syntax"1

<input type='button' id='red' :class='["btn", {"btn-danger": (count % 3 === 0)}]'  />

The documentation uses double quotes and I attempted to use those but it didn't appear to work - perhaps because btn-danger needs to be surrounded by quotes.

<input type='button' id='red' :class="[btn, {'btn-danger': (count % 3 === 0)}]" />

There doesn't appear to be anything dynamic about the styles in styleObject, so those can be moved out of the business logic and maintained with the other styles in the CSS section.


The interval function could be simplified using the increment operator:

setInterval(function() {
  app.count++;
}, 1000);

See the rewritten code that utilizes the advice above.

var app = new Vue({
  el: '#app',
  data: {
    count: 0    
  }
});

setInterval(function() {
  app.count++;
}, 1000);
#light {
  background-color: yellow;
  display: inline-block;
  border: 2px solid black;
  margin: 10px;
  padding: 5px;
}

#light .btn {
  display: block;
  width: 30px;
  margin: 0;
  border-radius: 50px;
  border: 1px solid black;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
<div id="app">
  <div id='light'>
    <input type='button' id='red' :class='["btn", {"btn-danger": (count % 3 === 0)}]'  />
    <br />
    <input type='button' id='yellow' :class='["btn", {"btn-warning": (count % 3 === 1)}]'  />
    <br />
    <input type='button' id='green' :class='["btn", {"btn-success": (count % 3 === 2)}]'  />
  </div>
</div>

1https://vuejs.org/v2/guide/class-and-style.html#Array-Syntax

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.