【问题标题】:Dynamic binding of v-model to computed propertyv-model 到计算属性的动态绑定
【发布时间】:2020-09-23 09:40:39
【问题描述】:

我有一个组件,我想在其中迭代具有计算属性的元素。

在正常情况下你会做这样的事情:

// Computed property
acquiredPrice: {
  get () {
    return value
  },
  set (value) {
    // set the value with some vuex magic
  },
},

然后像这样在模板中引用它:

<v-text-field
    v-model="acquiredPrice"
>
</v-text-field>

这正如预期的那样工作。但是我想做以下事情

// computed property
steps () {
  return [
    {
      allowed: true,
      text: 'Some question?',
      type: 'integer',
      model: this.acquiredPrice, // reference to the computed property
    },
  ]
},
<!-- inside template -->
<template v-for="step in steps">
  <v-row
      :key="step.text"
  >
    <v-col>
        <h4>{{step.text}}</h4>
        <!-- This does not work. Only in retrieving the value -->
        <v-text-field
            v-model="step.model"
        >
        </v-text-field>
    </v-col>
  </v-row>
</template>

所以核心问题是,当我遍历这些步骤并使用 step.model 来引用计算属性时,我会丢失 setter。即,当在字段中输入时,setter 方法永远不会被命中。

也许有一些方法可以通过字符串名称访问计算属性,所以我可以避免 dict 中的实际值?

例如(这只是我想要的伪代码)v-model=$computed['acquiredPrice']

可以在此处查看说明问题的完整 PoC:

<template>
  <div class="">
    <template v-for="step in steps">
      <v-row
          :key="step.text"
      >
        <v-col>
            <h4>{{step.text}}</h4>
            <!-- This does not work. Only in retrieving the value -->
            <v-text-field
                v-model="step.model"
            >
            </v-text-field>
        </v-col>
      </v-row>
    </template>
    <!-- This works just as expected -->
    <v-text-field
        v-model="acquiredPrice"
    >
    </v-text-field>
  </div>
</template>

<script>
  export default {
    name: 'redacted',
    props: {
    },
    data: () => ({
    }),
    computed: {
      acquiredPrice: {
        get () {
          return value
        },
        set (value) {
          // set the value with some vuex magic
          // THIS IS NEVER HIT WHEN IT IS REFERENCED FROM step.model ON LINE 13
        },
      },
      steps () {
        return [
          {
            allowed: true,
            text: 'Some question?',
            type: 'integer',
            model: this.acquiredPrice,
          },
        ]
      },
    },
    components: {
    },
    methods: {
    },
    mounted () {
    },
  }
</script>

【问题讨论】:

  • 也许你可以使用观察者模式来代替deep: true
  • 为什么不 v-bind 到 acquiredPrice

标签: javascript vue.js vuejs2


【解决方案1】:

根本问题在这一行:

model: this.acquiredPrice, // reference to the computed property

因为您没有将 acquiredPrice 计算属性的引用分配给 model,所以您正在调用它的 getter 并分配它返回的值...

没有像 $computed 这样的东西,因为它不需要 - 计算的 prop 只是组件的另一个成员,因此您可以像 this["acquiredPrice"] 一样访问它,并且由于模板中没有 this,您可以使用 小技巧使用该方法并从中返回this....

整体解决方案:

new Vue({
  data() {
    return {
      counter: 10
    };
  },
  computed: {
    acquiredPrice: {
      get() {
        return this.counter;
      },
      set(value) {
        // just placeholder as we dont have Vuex here
        this.counter = value;
        console.log("Updating counter", value)
      }
    },
    steps() {
      return [{
        allowed: true,
        text: 'Some question?',
        type: 'integer',
        model: 'acquiredPrice'
      }, ]
    },
  },
  methods: {
    self() {
        return this
    }
  }
}).$mount("#app");
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  {{ counter }}

  <div v-for="step in steps" :key="step.text">
    <h4>{{step.text}}</h4>    
    <input v-model="self()[step.model]" />
  </div>
</div>

【讨论】:

  • 这正是我所需要的!非常感谢您简洁而完美的回答。
猜你喜欢
  • 2019-06-09
  • 1970-01-01
  • 2018-01-09
  • 2020-04-13
  • 2023-04-08
  • 2020-10-29
  • 2019-05-02
  • 2020-07-15
  • 2017-04-16
相关资源
最近更新 更多