vue.js计算属性未触发

时间:2017-08-17 08:01:14

标签: javascript vue.js vuejs2 vue-component

使用此标记不会触发Vue JS计算属性

<!-- 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: {
      }
    },
  computed: {
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 - 触发updateSelected方法。

<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

我已经检查了调试器,并且可以看到所有正确的属性都可用。

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...

我有一个计算属性,应根据plant_price的值更新selected.plant.selected_variation

我抓住selected.plant.selected_variation并搜索变体以检索价格。如果不存在差异,则给出工厂价格。

我在每个产品上都有一个方法来更新所选的工厂。单击该产品将填充selected.plant并触发计算的plant_price以更新价格(因为selected.plant.selected_variation的值已更改)。

但是,计算的plant_price不是由select触发的。选择一个新的变体做它应该的,它更新selected.plant.selected_variation。然而,我的plant_price似乎并没有被它触发。

所以我通过取消嵌套selected.plant.selected_variation来重构我的代码。我现在把它挂在数据对象上

data = {
    selected_variation: ''
    }

并更改我的计算机属性以引用数据作为this.selected_variation。我的计算属性现在有效???这对我没有意义吗?

2 个答案:

答案 0 :(得分:2)

selected.plant.selected_variation不是被动的,VM看不到您对其所做的任何更改,因为您在创建VM后进行了设置。

你可以使它与Vue.set()

反应

当您的AJAX完成后,请致电

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

答案 1 :(得分:0)

有两种方法可以做到这一点,你正在处理的是一个嵌套对象,所以如果你想通知selected对你必须使用的其他人的更改

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

在代码段中,我使用setTimeout方法中的created来模拟Ajax调用。

另一种方法是将plant_price作为computed属性,而不是将selected作为plant_price属性,您可以观察嵌套属性的更改  观察者中handler的{​​{1}},然后更新plant_price_from_watch中的Vue.component('v-select', VueSelect.VueSelect); const app = new Vue({ el: '#app', data: { plant_price_from_watch: 'not available', selected: { type: {a: '' , b: ''}, vehicle: "Truck" } }, computed: { 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.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script> <script src="https://cdnjs.cloudflare.com/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>

/resources/assets/js/bootstrap.js
window.axios.defaults.headers.common = {
    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
    'X-Requested-With': 'XMLHttpRequest'
};