What is the simplest way to toggle a class on/off

2019-07-28 17:04发布

I have seen several examples of how to toggle a class in Vue.js like this:

new Vue({
  el: "#app",
  data: {
    isActive: false
  }
});
.demo {
  width: 100px;
  height: 100px;
  background-color: red;
  display: inline-block;
}

.active {
  border: #000 solid 3px;
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.js"></script>

<div id="app">
    <div class="demo" @click="isActive = !isActive" :class="{active: isActive}"></div>
</div>

Clicking the element toggles if it is active true or false and you are then toggling the class. This is fine, but doesn't work when you have more elements that you also what to toggle and active class on and off like this:

new Vue({
  el: "#app",
  data: {
    isActive: false
  }
});
.demo {
  width: 100px;
  height: 100px;
  background-color: red;
  display: inline-block;
}

.active {
  border: #000 solid 3px;
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.js"></script>

<div id="app">
    <div class="demo" @click="isActive = !isActive" :class="{active: isActive}"></div>
  <div class="demo" @click="isActive = !isActive" :class="{active: isActive}"></div>
  <div class="demo" @click="isActive = !isActive" :class="{active: isActive}"></div>
</div>

Now we are toggling the same for all of them, even though we just want to toggle the individual element that was clicked.

I know in jQuery this would be very simple:

$('.demo').on('click', function() {
  $(this).toggleClass('active');
});
.demo {
  width: 100px;
  height: 100px;
  background-color: red;
  display: inline-block;
}

.active {
  border: #000 solid 3px;
 }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<div id="app">
  <div class="demo"></div>
  <div class="demo"></div>
  <div class="demo"></div>
</div>

I have seen an example that required an entire component to be made that needed to be exported/imported just to scope the isActive property to that individual div, however that solution seems like a lot for such simple behavior. So what would be the simplest solution to toggling an .active class on/off of individual elements like my jQuery example?

3条回答
戒情不戒烟
2楼-- · 2019-07-28 17:50

The issue is that by binding a parent property to each instance, they share the parent's state and no longer represent their own state. One "vue-y" solution is to create a unique isActive state per instance via individual properties or an array of properties.

new Vue({
  el: "#app",
  data: {
    isActive1: false,
    isActive2: false, 
    isActive3: false,
  }
});
.demo {
  width: 100px;
  height: 100px;
  background-color: red;
  display: inline-block;
}

.active {
  border: #000 solid 3px;
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.js"></script>

<div id="app">
    <div class="demo" @click.self="isActive1 = !isActive1" :class="{active: isActive1}"></div>
  <div class="demo" @click.self="isActive2 = !isActive2" :class="{active: isActive2}"></div>
  <div class="demo" @click.self="isActive3 = !isActive3" :class="{active: isActive3}"></div>
</div>

There are additional benefits to this type of unique representation. You may need to do more at a future date than just toggle a class on and off. You now have a way to identify active elements which will lead to a more scaleable application.

Keep in mind that at this point it would make more sense to encapsulate your behavior into a component so that you can reuse it with isolated scope.

查看更多
我只想做你的唯一
3楼-- · 2019-07-28 18:00

I know the vuejs guide (Class and Style Bindings) uses data properties, but is this mandatory?

new Vue({
  el: "#app",
  data: {},
  methods: {
    toggleMe: function (event) {
      event.target.classList.toggle('active');
    }
  }  
});
.demo {
  width: 100px;
  height: 100px;
  background-color: red;
  display: inline-block;
}

.active {
  border: #000 solid 3px;
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.js"></script>

<div id="app">
  <div class="demo" @click="toggleMe"></div>
  <div class="demo" @click="toggleMe"></div>
  <div class="demo" @click="toggleMe"></div>
</div>

查看更多
走好不送
4楼-- · 2019-07-28 18:02

You can do that with java script like that:

new Vue({
	el: "#app",
	methods:{
		setActive(event){
		   event.target.classList.toggle("active");
		}
	}
});
.demo {
    width: 100px;
    height: 100px;
    background-color: red;
    display: inline-block;
}

.active {
    border: #000 solid 3px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.js"></script>

<div id="app">
     <div class="demo" @click="setActive"></div>
     <div class="demo" @click="setActive"></div>
     <div class="demo" @click="setActive"></div>
</div>

Or as you mentioned you can create a component like that:

Vue.component('test-component',{
    template: `<div class="demo" @click="isActive = !isActive" :class="{active: isActive}"></div>`,
    data(){
        return {
            isActive: false
        }
    }
});

html:

<div id="app">
     <test-component></test-component>
     <test-component></test-component>
     <test-component></test-component>
</div>
查看更多
登录 后发表回答