问题
I have general component and vuex store. For easy two-way binding I use vuex-map-fields. On component side it has mapFields
method which creates get&set with mutations.
I want to pass namespace
from vuex module with props
but it seems to be impossible.
<my-component namespace="ns1" />
// my-component code
export default {
props: ["namespace"],
computed: {
...mapFields(??this.namespace??, ["attr1", "attr2"])
}
}
Of course, there is no way to use this
in such way so we don't have access to props. How can I specify namespace as prop in such case?
回答1:
The problem (as you probably gathered) is that computed properties are constructed before this
is available, but you can get around it by deferring resolution of the this.namespace
property until the computed property is called (which won't happen until component construction is finished).
The concept is based on this post Generating computed properties on the fly.
The basic pattern is to use a computed with get()
and set()
computed: {
foo: {
get() { this.namespace...},
set() { this.namespace...},
}
}
but rather than type it all out in the component we can create a helper function based on the vuex-map-fields mapFields()
function (see here for the original).
The normalizeNamespace()
function that comes with vuex-map-fields does not support what we want to do, so we drop it and assume the namespace is always passed in (and that the store module uses the standard getField
and updateField
functions).
I have adapted one of the vuex-map-fields Codesandbox examples here.
Note the namespace is in data
rather than props
for conveniance, but props
should work also.
Template
<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>
Helper
<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>
Store
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/>"
});
来源:https://stackoverflow.com/questions/54833150/vue-how-to-use-component-prop-inside-mapfields