Проблема (как вы, вероятно, поняли) состоит в том, что вычисляемые свойства создаются до того, как станет доступен this
, но вы можете обойти его, отложив разрешение свойства this.namespace
до вызова вызываемого свойства (что не будетпроизойдет до тех пор, пока не будет завершено построение компонента).
Концепция основана на этом посте Генерация вычисляемых свойств на лету .
Основной шаблон заключается в использовании вычисляемого с get()
и set()
computed: {
foo: {
get() { this.namespace...},
set() { this.namespace...},
}
}
, но вместо того, чтобы вводить все это в компоненте, мы можем создать вспомогательную функцию на основе функции vuex-map-fields mapFields()
(см. здесь для оригинала).
Функция normalizeNamespace()
, которая поставляется с полями vuex-map-fields, не поддерживает то, что мы хотим сделать, поэтому мы отбрасываем ее и предполагаем, что пространство именвсегда передается (и что модуль store использует стандартные функции getField
и updateField
).
Я адаптировал одно из примеров кодов-полей vuex-map-fields здесь .
нетт. е. пространство имен находится в 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/>"
});