简体   繁体   中英

Vue.js 2 dynamically adding and removing classes in looped elements

I have a project here where I need to add and remove layers of images, using vue.js 2. I am building up a pizza where I need to add toppings. My current solution has a flaw - it removes all other elements/ pizza toppings when I add a new one.

The toppings are generated from an array which I loop through.

Can you please help, I am sure this is easy but me being a rookie in vue.js I have already struggled for hours... Thanks!

<div id="app" class="container-fluid">
      <div class="row">
          <div class="left-container">
              <h2>add your ingredients:</h2>
              <div v-for="(item, index) in pizzas"  v-bind:key="index">
                <button class="btn btn-primary" v-on:click="show == index ? show = -1 : show = index">{{ item.pizza }}</button>
              </div>
              <div class="submit-buttons">
                  <button class="btn btn-primary reset-pizza" v-on:click="show = -1">Reset pizza</button>
                  <a href="http://fb.com" target="_blank"><button class="btn btn-primary submit-pizza">Share pizza</button></a>
              </div>
          </div>
          <div class="right-container">
              <ul class="pizza-layers">
                <li v-for="(item, index) in pizzas" class="pizza-canvas" v-bind:class="item.class" v-if="show == index"></li>
                <li class="pizza-canvas pizza-canvas--topping-base"></li>
              </ul>
          </div>
      </div>
    </div>

<script>
 new Vue({
    el: '#app',
    data: {
      pizzas: [
        { pizza: 'Salami', class: 'pizza-canvas--topping-salami' },        
        { pizza: 'Rucolla', class: 'pizza-canvas--topping-rucolla' },
        { pizza: 'Cheese', class: 'pizza-canvas--topping-cheese' }
      ],
      show: {},
    },
  })
</script>

To allow for multiple toppings, this.show should be an array, instead of an object.

Once you change that, you'd need to modify the click event handler to add/remove the topping based on whether or not the topping is already part of show .

Also, while displaying the topping, you'd need to check its existence using show.includes(index) instead of show == index - since this.show is an array.

In the snippet below, I've applied these changes, and added some background colors to visualize how the toppings are added or removed.

 new Vue({ el: '#app', data: { pizzas: [{ pizza: 'Salami', class: 'pizza-canvas--topping-salami' }, { pizza: 'Rucolla', class: 'pizza-canvas--topping-rucolla' }, { pizza: 'Cheese', class: 'pizza-canvas--topping-cheese' } ], show: [], }, methods: { addTopping(event, item, index) { if(this.show.includes(index)) { this.show.splice(this.show.indexOf(index),1); } else { this.show.push(index); } } } }) 
 .pizza-canvas--topping-salami { background-color: red; } .pizza-canvas--topping-rucolla { background-color: yellow; } .pizza-canvas--topping-cheese { background-color: blue; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.2/vue.min.js"></script> <div id="app" class="container-fluid"> <div class="row"> <div class="left-container"> <h2>add your ingredients:</h2> <div v-for="(item, index) in pizzas" v-bind:key="index"> <button class="btn btn-primary" v-on:click="addTopping(event, item, index)">{{ item.pizza }}</button> </div> <div class="submit-buttons"> <button class="btn btn-primary reset-pizza" v-on:click="show = []">Reset pizza</button> <a href="http://fb.com" target="_blank"><button class="btn btn-primary submit-pizza">Share pizza</button></a> </div> </div> <div class="right-container"> <ul class="pizza-layers"> <li v-for="(item, index) in pizzas" class="pizza-canvas" v-bind:class="item.class" v-if="show.includes(index)"></li> <li class="pizza-canvas pizza-canvas--topping-base"></li> </ul> </div> </div> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM