从vue.js中的store获得的计算属性的setter

时间:2017-11-15 10:33:24

标签: vue.js vuex

我想制作两个从store.js获取价值的复选框,并通过表单将其发送到后端:

        <label>Notify me 
            <input type="checkbox" v-model="notification" value="notification"   />     
        </label>

        <label>Email me 
            <input type="checkbox" v-model="email" value="email"   />       
        </label>

我将值作为计算属性获取:

computed: {
    BASE_URL () {
    return this.$store.state.BASE_URL;  
      }, 
  notification () {
    return this.$store.state.notification; 
      },

  email () {
    return this.$store.state.email; 
      }
  }

问题是选中复选框不会更改商店中的值,除此之外,我在控制台中收到此警告,例如:

vue.esm.js?65d7:479 [Vue warn]: Computed property "notification" was assigned to but it has no setter.

我知道可以在vue.js文档中定义计算属性中的setter,如described,但是当有多个值要设置时,我不知道怎么做,比如我的特殊案例。

非常感谢您帮助解决此问题。

1 个答案:

答案 0 :(得分:12)

要更改Vuex状态,您需要一个变异。

如果您有更改setNotification状态的变异notification,则可以在组件中配置属性,如下所示:

computed: {
    notification: {
        get() { return this.$store.state.notification; },
        set(value) { this.$store.commit('setNotification', value); },
    },
},

您现在可以正常v-model="notification"绑定到它。

有关详细信息,请参阅文档中的Form Handling

因为这是我在项目中经常做的事情,所以我编写了一个生成计算属性的辅助函数:

function mapStateTwoWay(...args) {
    const result = {};

    if (args.length === 1) {
        for (const prop of Object.keys(args[0])) {
            result[prop] = {
                get() { return this.$store.state[prop]; },
                set(value) { this.$store.commit(args[0][prop], value); },
            };
        }
    } else {
        for (const prop of Object.keys(args[1])) {
            result[prop] = {
                get() { return this.$store.state[args[0]][prop]; },
                set(value) { this.$store.commit(args[0] + '/' + args[1][prop], value); },
            };
        }
    }

    return result;
}

像这样使用:

computed: {
    ...mapStateTwoWay({
        notifications: 'setNotifications',
        email: 'setEmail',
    }),

    // Namespaced
    ...mapStateTwoWay('namespace', {
        notifications: 'setNotifications',
        email: 'setEmail',
    }),
}