【问题标题】:vue.js computed property not triggeredvue.js 计算属性未触发
【发布时间】:2018-01-25 13:03:13
【问题描述】:

使用此标记不会触发 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...

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

我抓住selected.plant.selected_variation 并搜索变体以检索价格。如果不存在变化,则给出植物价格。

我对每个产品都有一个更新所选植物的方法。单击产品会填充 selected.plant 并触发计算的 plant_price 以更新价格(因为 selected.plant.selected_variation 的值已更改)。

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


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

data = {
    selected_variation: ''
    }

并更改我的计算机属性以将数据引用为 this.selected_variation。我的计算属性现在可以工作???这对我来说毫无意义?

【问题讨论】:

    标签: javascript vue.js vuejs2 vue-component


    【解决方案1】:

    selected.plant.selected_variation 不是响应式的,VM 看不到您对其所做的任何更改,因为您在创建 VM 之后设置它。

    你可以用 Vue.set() 让它反应

    当你的 AJAX 完成后,调用

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

    【讨论】:

    • 谢谢@SpeekaDievs,对不起 - 我没有很好地解释自己......我会更新我的问题
    • 您对我描述的问题的回答是正确的。我只是没有很好地描述它......
    • 你把这行代码放在哪里,你能解释一下参数吗?谢谢
    【解决方案2】:

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

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

    在sn-p中我在created方法中使用了setTimeout来模拟Ajax调用。

    您可以这样做的另一种方法是将plant_price 作为computed 属性,您可以观察嵌套属性的变化 观察者中的selected,然后更新handler中的plant_price,您可以在sn-p中查看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>

    【讨论】:

    • 感谢 Kevlai22 - 恐怕我已经编辑了我的问题,因为我发布的问题充满了错误...请参阅问题编辑
    • @Rob 我不太明白你的updateSelected 方法,你传递给a 是什么??
    • 整个植物对象。我有一个我渲染出来的植物列表(这个列表是通过 ajax 获得的)。在每个植物上,我都附上了更新方法。我只是将整个工厂作为一个更新函数传入。这将更新选定的植物。为了清楚起见,我通过将 a 更改为植物来更新我的问题
    • @Rob 所以实际上有一个单独的植物列表(我们称之为plantList),它是通过ajax调用检索的,updateSelected将更新放入selected.plant的内容,这将影响在下拉列表中选择什么??
    猜你喜欢
    • 2017-07-22
    • 1970-01-01
    • 2017-07-29
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    相关资源
    最近更新 更多