【问题标题】:How to manually add getters/mutations to a Vuex store, after it's already created?如何在 Vuex 商店创建后手动添加 getter/mutations?
【发布时间】:2018-10-24 04:08:29
【问题描述】:

我正在尝试在我的一个 Vuejs 组件的“已创建”生命周期挂钩中添加新变量、getter 和突变。变量工作正常。但是对于 getter/mutations,似乎并不像向 vuex 存储对象添加新函数那么容易。我要解决的问题是创建“共享”可重用组件。

这是组件:

<template>
  <div>
    <h2 class="headline">Number of items:</h2>
    <v-select
      :items="limits"
      item-value="value"
      item-text="text"
      label="Select"
      v-model="selected_limit"/>
  </div>
</template>

<script>
  import {selectLimitComponentVariables} from './index';
  import {selectLimitComponentGetters} from './getters';
  import {selectLimitComponentMutations} from './mutations';

  export default {
    created: function () {
      // Add the variables
      Object.assign(this.$store.state[this.ns], selectLimitComponentVariables(this.var_prefix));
      // Add the getters
      Object.assign(this.$store.getters, selectLimitComponentGetters(this.ns, this.var_prefix));
      // Add the mutations
      Object.assign(this.$store._mutations, selectLimitComponentMutations(this.ns, this.var_prefix));
    },
    name: 'SelectLimitComponent',
    props: {
      ns: {
        type: String,
        default: null
      },
      var_prefix: {
        type: String,
        default: ''
      }
    },
    computed: {
      selected_limit: {
        get () {
          return this.$store.state[this.ns].selected_limit;
        },
        set (value) {
          this.$store.commit(`${this.ns}/update${this.var_prefix}selected_limit`, value)
        }
      },
      limits: {
        get() {
          return this.$store.state[this.ns].limits;
        }
      }
    }
  }
</script>

这里是导入的函数。 选择限制组件变量:

export const selectLimitComponentVariables = function (prefix) {
  return {
    [`${prefix}selected_limit`]: '100',
    [`${prefix}limits`]: [
      {'text': '10', 'value': '10'},
      {'text': '50', 'value': '50'},
      {'text': '100', 'value': '100'},
      {'text': '250', 'value': '250'},
      {'text': 'No limit', 'value': '-1'}]}
};

selectLimitComponentGetters:

export const selectLimitComponentGetters = function(namespace, prefix){
  return {
    [`${namespace}/${prefix}selected_limit`]: state => state[`${prefix}selected_limit`]
  }
};

selectLimitComponentMutations:

export const selectLimitComponentMutations = function (namespace, prefix){
  return {
    [`${namespace}/update${prefix}selected_limit`]: (state, newLimit) => state[`${prefix}selected_limit`] = newLimit
  }
};

在创建 vuex 存储之后,有没有办法手动添加或注册新的 getter/mutations?

【问题讨论】:

    标签: javascript vue.js vuejs2 vuex


    【解决方案1】:

    最好使用vuex的store.registerModule特性动态添加新模块到vuex

    this.$store.registerModule(`${this.ns}selected_limit`, {
      state: selectLimitComponentVariables...,
      getters: selectLimitComponentGetters...,
      mutations: selectLimitComponentMutations...,
      namespaced: true
    })
    

    您可以在https://vuex.vuejs.org/en/modules.htmlDynamic Module Registration部分查看官方文档

    【讨论】:

      【解决方案2】:

      看起来你想要做的是拥有每个组件的 Vuex 状态。

      如果你像那样随意修改 Vuex 架构,那么管理状态分离将变得非常困难(你只是在修补 Vuex 根状态)。

      这是另一种方法。您可以创建一个单独的 Vuex 模块并在组件的 beforeCreate 挂钩中动态注册它。

      Vue.use(Vuex);
      
      const HomeModule = {
        namespaced: true,
        state() {
          return {
            count: 0,
          };
        },
        mutations: {
          increment(state) {
            state.count++;
          },
        },
      };
      
      const ns = 'home';
      
      Vue.component('home', {
        template: '<div><button @click="increment">+</button> {{ count }}</div>',
        beforeCreate() {
          if (!this.$store.state[ns]) {
            this.$store.registerModule(ns, HomeModule);
          }
        },
        computed: Vuex.mapState(ns, ['count']),
        methods: Vuex.mapMutations(ns, ['increment']),
      });
      
      new Vue({
        el: '#app',
        store: new Vuex.Store(),  // Empty root store
      });
      <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.3/vuex.js"></script>
      
      <div id="app">
        <home></home>
      </div>
      • 我在这里使用了 ns 全局变量,但您可以从示例中的 prop 中获取它。
      • 您可以动态构建模块,而不是硬编码。
      • 如有必要,您也可以在组件销毁时取消注册模块。

      【讨论】:

      • 在 beforeCreate() 中比 created() 更好。计算属性可能会在 created() 之前被触及。
      • 类似的东西也可以用&lt;keep-alive/&gt;实现
      【解决方案3】:

      在实例化后添加值的问题在于,如果不使用set,它们不会成为反应式

      当您添加一个新属性时,该数据不存在 被观测到。由于 ES5 的限制和保证一致 跨浏览器的行为,Vue.js 无法检测属性 添加/删除。最佳实践是始终声明属性 这需要预先做出反应。在您绝对需要的情况下 要在运行时添加或删除属性,请使用全局 Vue.set 或 Vue.delete 方法。

      试试这个

      import Vue from 'vue';
      
      export const selectLimitComponentMutations = function (namespace, prefix){
        return {
          [`${namespace}/update${prefix}selected_limit`]: (state, newLimit) => {
            Vue.$set(state, `${prefix}selected_limit`, newLimit);
          }
        }
      };
      

      【讨论】:

        猜你喜欢
        • 2021-08-25
        • 2019-01-07
        • 2021-01-22
        • 2012-10-16
        • 2021-04-23
        • 2021-04-27
        • 2017-11-09
        • 1970-01-01
        • 2021-08-08
        相关资源
        最近更新 更多