admin管理员组

文章数量:1279182

Vue JS puted property is not triggered With this markup

<!-- language: lang-html -->
<p>£{{plant_price}}</p>

    <div v-if="selected.plant.variations.length > 0 ">
      <select v-model="selected.plant.selected_variation" class="form-control">
        <!-- inline object literal -->
        <option v-for="(variation, i) in selected.plant.variations" :selected="variation.id == selected.plant.selected_variation ? 'selected' : ''":value="variation.id">
          {{variation.name}}
        </option>
      </select>
    </div>

<!-- language: lang-js -->
var app = new Vue({
  el: '#vueApp',
  data: {
    selected: {
      type: {a: '' , b: ''},
      vehicle: '',
      plant: {
      }
    },
  puted: {
plant_price: function() {
  if (this.selected.plant.variations.length > 0 ) {
      var variant = _.find(this.selected.plant.variations, {id: this.selected.plant.selected_variation });
      return variant.price;
  } else {
    return this.selected.plant.price;
  }
}
...

selected.plant is populated by clicking on a plant - triggering the updateSelected method.

<div class="col-sm-4" v-for="(plant, i) in step2.plants">
          <div v-on:click="updateSelected(plant)" ....

 methods: {
      updateSelected: function(plant) {
             this.selected.plant = plant; // selected plant
             if (this.selected.plant.variations.length > 0 ) {
                 this.selected.plant.selected_variation = this.selected.plant.variations[0].id; // set the selected ID to the 1st variation

I have checked through the debugger, and can see that all the correct properties are available.

selected:Object
    type:Object
    vehicle: "Truck"
    plant:Object
       id:26
       price:"52"
       regular_price:"100"
       selected_variation:421
       variations:Array[2]
          0:Object
              id:420
              name:"small"
              price:52000
              regular_price:52000
          1:Object
               etc...

I have a puted property, which should update the plant_price based on the value of selected.plant.selected_variation.

I grab selected.plant.selected_variation and search through the variations to retrieve the price. If no variation exists, then the plant price is given.

I have a method on each product to update the selected plant. Clicking the product populates the selected.plant and triggers the puted plant_price to update the price (as the value of selected.plant.selected_variation has changed).

However, the puted plant_price is not triggered by the select. Selecting a new variant does what its supposed to, it updates selected.plant.selected_variation. Yet my plant_price doesn't seem to be triggered by it.


So I refactored my code by un-nesting selected.plant.selected_variation. I now hang it off the data object as

data = {
    selected_variation: ''
    }

and alter my puter property to reference the data as this.selected_variation. My puted property now works??? This makes no sense to me?

Vue JS puted property is not triggered With this markup

<!-- language: lang-html -->
<p>£{{plant_price}}</p>

    <div v-if="selected.plant.variations.length > 0 ">
      <select v-model="selected.plant.selected_variation" class="form-control">
        <!-- inline object literal -->
        <option v-for="(variation, i) in selected.plant.variations" :selected="variation.id == selected.plant.selected_variation ? 'selected' : ''":value="variation.id">
          {{variation.name}}
        </option>
      </select>
    </div>

<!-- language: lang-js -->
var app = new Vue({
  el: '#vueApp',
  data: {
    selected: {
      type: {a: '' , b: ''},
      vehicle: '',
      plant: {
      }
    },
  puted: {
plant_price: function() {
  if (this.selected.plant.variations.length > 0 ) {
      var variant = _.find(this.selected.plant.variations, {id: this.selected.plant.selected_variation });
      return variant.price;
  } else {
    return this.selected.plant.price;
  }
}
...

selected.plant is populated by clicking on a plant - triggering the updateSelected method.

<div class="col-sm-4" v-for="(plant, i) in step2.plants">
          <div v-on:click="updateSelected(plant)" ....

 methods: {
      updateSelected: function(plant) {
             this.selected.plant = plant; // selected plant
             if (this.selected.plant.variations.length > 0 ) {
                 this.selected.plant.selected_variation = this.selected.plant.variations[0].id; // set the selected ID to the 1st variation

I have checked through the debugger, and can see that all the correct properties are available.

selected:Object
    type:Object
    vehicle: "Truck"
    plant:Object
       id:26
       price:"52"
       regular_price:"100"
       selected_variation:421
       variations:Array[2]
          0:Object
              id:420
              name:"small"
              price:52000
              regular_price:52000
          1:Object
               etc...

I have a puted property, which should update the plant_price based on the value of selected.plant.selected_variation.

I grab selected.plant.selected_variation and search through the variations to retrieve the price. If no variation exists, then the plant price is given.

I have a method on each product to update the selected plant. Clicking the product populates the selected.plant and triggers the puted plant_price to update the price (as the value of selected.plant.selected_variation has changed).

However, the puted plant_price is not triggered by the select. Selecting a new variant does what its supposed to, it updates selected.plant.selected_variation. Yet my plant_price doesn't seem to be triggered by it.


So I refactored my code by un-nesting selected.plant.selected_variation. I now hang it off the data object as

data = {
    selected_variation: ''
    }

and alter my puter property to reference the data as this.selected_variation. My puted property now works??? This makes no sense to me?

Share Improve this question edited Aug 17, 2017 at 10:16 Rob asked Aug 17, 2017 at 8:01 RobRob 1,6363 gold badges25 silver badges54 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

selected.plant.selected_variation isn't reactive and VM doesn't see any changes you make to it, because you set it after the VM is already created.

You can make it reactive with Vue.set()

When your AJAX is finished, call

Vue.set(selected, 'plant', {Plant Object})

There're two ways you can do it, what you are dealing with is a nested object, so if you want to notify the changes of selected to the others you have to use

this.$set(this.selected, 'plant', 'AJAX_RESULT')

In the snippet I used a setTimeout in the created method to simulate the Ajax call.

Another way you can do it is instead of making plant_price as a puted property, you can watch the changes of the nested properties of selected in the watcher, and then update plant_price in the handler, you can check out plant_price_from_watch in the snippet.

Vue.ponent('v-select', VueSelect.VueSelect);

const app = new Vue({
  el: '#app',
  data: {
    plant_price_from_watch: 'not available',
    selected: {
      type: {a: '' , b: ''},
      vehicle: "Truck"
    }
  },
  puted: {
    plant_price() {
      return this.setPlantPrice();
    }
  },
  watch: {
    selected: {
      handler() {
        console.log('changed');
        this.plant_price_from_watch = this.setPlantPrice();
      },
      deep: true
    }
  },
  created() {
    setTimeout(() => {
      this.$set(this.selected, 'plant', {
        id: 26,
        price: '52',
        regular_price: '100',
        selected_variation: 421,
        variations: [
          {
            id: 420,
            name: "small",
            price: 52000,
            regular_price: 52000
          },
          {
            id: 421,
            name: "smallvvsvsfv",
            price: 22000,
            regular_price: 22000
          }
        ]
      })
    }, 3000);
  },
  methods: {
    setPlantPrice() {
      if (!this.selected.plant) {
        return 'not available'
      }
      if (this.selected.plant.variations.length > 0 ) {
          const variant = _.find(this.selected.plant.variations, {id: this.selected.plant.selected_variation });
          return variant.price;
      } else {
        return this.selected.plant.price;
      }
    }
  }
});
<script src="https://cdnjs.cloudflare./ajax/libs/lodash.js/4.17.4/lodash.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/vue/2.4.2/vue.js"></script>
<div id="app">
  <p>£{{plant_price}}</p>
  <p>£{{plant_price_from_watch}}</p>
  <div v-if="selected.plant && selected.plant.variations.length > 0 ">
    <select v-model="selected.plant.selected_variation" class="form-control">
      <!-- inline object literal -->
      <option v-for="(variation, i) in selected.plant.variations" :selected="variation.id == selected.plant.selected_variation ? 'selected' : ''":value="variation.id">
        {{variation.name}}
      </option>
    </select>
  </div>
</div>

本文标签: javascriptvuejs computed property not triggeredStack Overflow