[Vuejs]-I have too many watchers in Vuejs, and my code is not scalable

3👍

Personally,

I would not define/hardcode each item but use a property of the object/item to define a state, so for example, type could be anything from hoodies to unicorns, and other value like size could be disabled by false etc. Then all you do in the ui is update the model/item.

Also, I would abstract out the items into a component for giggles.

Vue.component('cart-item', {
  template: '#cart-item',
  props: ['data', 'index'],
  data() {
    return {
      item: {
        type: this.data.type,
        price: this.data.price,
        size: this.data.size,
        qty: this.data.qty
      }
    }
  },
  methods: {
    updateOrder(e) {
      this.$emit('on-update', this.item, this.index)
    }
  }
});

//
var vm = new Vue({
  el: '#app',
  computed: {
    cartTotal: function() {
      let total = 0
      this.items.forEach(item => {
        total = total + item.qty * item.price
      })
      return total
    }
  },
  data() {
    return {
      items: [{
        type: 'T-shirt',
        price: 9.99,
        size: '',
        qty: 0
      }, {
        type: 'Unicorn Plush Toy',
        price: 3.99,
        size: false,
        qty: 0
      }]
    }
  },
  methods: {
    updateCart(value, index) {
      this.items[index] = Object.assign(this.items[index], value);
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.14/vue.min.js"></script>

<div id="app">
  <h1>Order Form</h1>

  <cart-item v-for="(item, index) in items" :data="item" :index="index" @on-update="updateCart"></cart-item>

  <p>Total cart cost: ${{ cartTotal }}</p>

  <pre>{{ items }}</pre>
</div>

<template id="cart-item">
   <div>
     <strong>{{ item.type }}</strong><br>
     <strong>{{ item.price }}</strong><br>
     <div v-if="item.size !== false">
     <label>Size</label>
     <select v-model="item.size" @change="updateOrder">
       <option>sml</option>
       <option>med</option>
       <option>lrg</option>
       <option>xlrg</option>
     </select>
     </div>
     <label>Qty</label>
     <input type="text" v-model="item.qty" @input="updateOrder"/>
   </div>
</template>

Leave a comment