【问题标题】:Vue: How to use component prop inside mapFieldsVue:如何在 mapFields 中使用组件道具
【发布时间】:2019-07-16 21:44:33
【问题描述】:

我有通用组件和 vuex 商店。为了方便双向绑定,我使用vuex-map-fields。在组件方面,它具有 mapFields 方法,该方法创建带有突变的 get&set。 我想用props从vuex模块传递namespace,但这似乎是不可能的。

<my-component namespace="ns1" />

// my-component code
export default {
  props: ["namespace"],
  computed: {
    ...mapFields(??this.namespace??, ["attr1", "attr2"])
  }
}

当然,没有办法以这种方式使用this,所以我们无法访问道具。在这种情况下如何将命名空间指定为道具?

【问题讨论】:

    标签: javascript vue.js vuex


    【解决方案1】:

    问题(正如您可能收集到的)是计算属性是在 this 可用之前构建的,但是您可以通过将 this.namespace 属性的解析推迟到计算属性被调用来解决它(这不会直到组件构建完成)。

    这个概念是基于这篇帖子Generating computed properties on the fly

    基本模式是使用 get()set() 进行计算

    computed: {
      foo: {
        get() { this.namespace...},
        set() { this.namespace...},
      }
    }
    

    但我们可以基于 vuex-map-fields mapFields() 函数创建一个辅助函数,而不是在组件中全部输入(参见 here 原文)。

    vuex-map-fields 自带的normalizeNamespace() 函数不支持我们想做的,所以我们把它去掉,假设总是传入命名空间(并且 store 模块使用标准的getFieldupdateField 函数)。

    我已经改编了 vuex-map-fields Codesandbox 示例之一here
    请注意,为了方便起见,命名空间位于 data 而不是 props,但 props 也应该可以工作。

    模板

    <template>
      <div id="app">
        <div>
          <label>foo </label> <input v-model="foo" /> <span> {{ foo }}</span>
        </div>
        <br />
        <div>
          <label>bar </label> <input v-model="bar" /> <span> {{ bar }}</span>
        </div>
      </div>
    </template>
    

    助手

    <script>
    
    const mapFields2 = (namespaceProp, fields) => {
      return Object.keys(fields).reduce((prev, key) => {
        const path = fields[key];
        const field = {
          get() {
            const namespace = this[namespaceProp];
            const getterPath = `${namespace}/getField`;
            return this.$store.getters[getterPath](path);
          },
          set(value) {
            const namespace = this[namespaceProp];
            const mutationPath = `${namespace}/updateField`;
            this.$store.commit(mutationPath, { path, value });
          }
        };
        prev[key] = field;
        return prev;
      }, {});
    };
    
    export default {
      name: "App",
      data() {
        return {
          nsProp: "fooModule"
        };
      },
      computed: {
        ...mapFields2("nsProp", { foo: "foo", bar: "bar" })
      }
    };
    </script>
    

    商店

    import Vue from "vue";
    import Vuex from "vuex";
    import { getField, updateField } from "vuex-map-fields";
    import App from "./App";
    
    Vue.use(Vuex);
    Vue.config.productionTip = false;
    
    const store = new Vuex.Store({
      modules: {
        fooModule: {
          namespaced: true,
          state: {
            foo: "initial foo value",
            bar: "initail bar value"
          },
          getters: {
            getField
          },
          mutations: {
            updateField
          }
        }
      }
    });
    
    new Vue({
      el: "#app",
      components: { App },
      store,
      template: "<App/>"
    });
    

    【讨论】:

      猜你喜欢
      • 2018-11-21
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 2018-10-20
      • 2020-09-12
      • 2021-02-20
      • 2021-07-31
      • 2018-12-21
      相关资源
      最近更新 更多