Vuex: 使用了vuex,v-model双向绑定不能用了,看文档上可以手动action,一个表单很多v-model怎么办?

Created on 3 Sep 2016  ·  7Comments  ·  Source: vuejs/vuex

用了vuex,不用 v-model,改用 value 绑定显示,注册 input 事件,手动调用 action 更新,如果一两个model还好,多的话呢,一个个的去手动调吗?
请问有没有好的解决方案?

Most helpful comment

刚好遇到这种情况,用下边的方法处理了下,不知道有没有更好的办法。

 <input type="text" v-model="form1.value1"/>
 <input type="text" v-model="form1.value2"/>

  data () {
    return {
      form1: Object.assign({}, this.$store.state.form1)
    }
  },
  watch: {
    form1: {
      handler (value, oldValue) {
        var copiedValue = Object.assign({}, value)
        this.$store.commit('setForm1', copiedValue)
      },
      deep: true
    }
  }

All 7 comments

@GITleonine1989 您好,请问下您现在还是用的这种解决方案吗?
我觉得官方给的这两种解决方案还是不太优雅,不过已经很好了。

  • 第一种就是您这总方案了,利用事件去更新。
  • 第二中当好多状态需要get, set的时候, computed属性不会变的好长
  • 我想到的一种是把当前的数据copy一份出来,进行v-model的绑定,当触发某个动作例如点击存储数据的时候把copy的这份数据再存储到store里面,这种也不合理,当保存数据入口多的情况下也得在好多入口上面加事件。

刚好遇到这种情况,用下边的方法处理了下,不知道有没有更好的办法。

 <input type="text" v-model="form1.value1"/>
 <input type="text" v-model="form1.value2"/>

  data () {
    return {
      form1: Object.assign({}, this.$store.state.form1)
    }
  },
  watch: {
    form1: {
      handler (value, oldValue) {
        var copiedValue = Object.assign({}, value)
        this.$store.commit('setForm1', copiedValue)
      },
      deep: true
    }
  }

可以抽出一个公用方法,生成 一系列的对象,其中包含各个参数的getset方法,然后用Object.assign合并到computed中
示例:v-model在strict下的使用的辅助函数
npm包: vuex-mapstate-modelvalue-instrict

@didikeke 这样newValue 和 oldValue一直是相等的,因为是同一个引用

我目前是使用這個,缺點是 Vuex 無法執行 createLogger()

<template>
  <div>
    <md-switch v-model="$av.autoplay" name="autoplay">Autoplay</md-switch>
    <md-switch v-model="$av.repeat" name="repeat">Repeat</md-switch>
  </div>
</template>

<script>
export default {
  computed: {
    $av() {
      return this.$store.state.awesomeVideo;
    }
  }
};
</script>

雖然有 Logger,但是一個 Input 都要寫一次

<template>
  <div>
    <md-switch v-model="autoplay" name="autoplay">Autoplay</md-switch>
    <md-switch v-model="repeat" name="repeat">Repeat</md-switch>
  </div>
</template>

<script>
export default {
  computed: {
    $av() {
      return this.$store.state.awesomeVideo;
    },
    autoplay: {
      get() { return this.$av.autoplay; },
      set(autoplay) { this.$store.commit('autoplay', { autoplay }); }
    },
    repeat: {
      get() { return this.$av.repeat; },
      set(repeat) { this.$store.commit('repeat', { repeat }); }
    }
  }
};
</script>
// mutations.js
export default {
  autoplay(state, { autoplay }) {
    state.autoplay = autoplay;
  },
  repeat(state, { repeat }) {
    state.repeat = repeat;
  }
};

@didikeke 最好是深克隆吧

I've made library, which makes two way binding much easier: https://github.com/yarsky-tgz/vuex-dot

in @didikeke case, for example, i'd recommend to edit his code such way:

<template>
   <input type="text" v-model="value1"/>
   <input type="text" v-model="value2"/>
</template>

<script>
  import { takeState } from 'vuex-dot';
  export default {
    ...takeState('form1')
      .expose(['value1', 'value2'])
      .commit('setForm')
      .map()
  };
</script>
Was this page helpful?
0 / 5 - 0 ratings