Vuex中的核心方法
-
state
: 基本数据。
-
getters
: 从基本数据派生的数据。
-
mutations
: 提交更改数据的方法,同步操作。
-
actions
: 像一个装饰器,包裹mutations
,使之可以异步。
-
modules
: 模块化Vuex
。
在Vue组件中获得Vuex状态
const store = new Vuex.Store({
state: {
count: 0
}
})
const vm = new Vue({
//..
store,computed: {
count: function(){
return this.$store.state.count;
}
},//..
})
mapState辅助函数
// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from "vuex";
export default {
// ...
computed: mapState({
// 箭头函数
count: state => state.count,// 传字符串参数 count 等同于 state => state.count
countAlias: "count",// 使用 this
countPlusLocalState: function(state) {
return state.count + this.localCount;
}
})
// ...
}
import { mapState } from "vuex";
export default {
// ...
computed: {
localComputed: function() { /* ... */ },// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
// ...
}
// ...
}
访问getters
const store = new Vuex.Store({
state: {
count:0
},
getters: {
// 单个参数
countDouble: function(state){
return state.count * 2
},// 两个参数
countDoubleAndDouble: function(state,getters) {
return getters.countDouble * 2
}
}
})
const vm = new Vue({
//..
store,computed: {
count: function(){
return this.$store.state.count;
},countDouble: function(){
return this.$store.getters.countDouble;
},countDoubleAndDouble: function(){
return this.$store.getters.countDoubleAndDouble;
}
},//..
})
mapGetters辅助函数
import { mapGetters } from "vuex";
export default {
// ...
computed: {
// 使用对象展开运算符将 getters 混入 computed 对象中
...mapGetters([
"countDouble","CountDoubleAndDouble",//..
]),...mapGetters({
// 映射 this.double 为 store.getters.countDouble
double: "countDouble"
})
}
// ...
}
定义mutation
const store = new Vuex.Store({
state: {
count: 1
},mutations: {
// 无提交荷载
increment: function(state) {
state.count++;
},// 提交荷载
incrementN: function(state,payload) {
state.count += payload.n;
}
}
})
//无提交荷载
this.$store.commit("increment");
//提交荷载
this.$store.commit("incrementN",{ n: 100 });
Mutations需遵守Vue的响应规则
- 最好提前在你的
store
中初始化好所有所需属性。
- 当需要在对象上添加新属性时,应该使用
Vue.set(obj,"newProp",1)
,或者以新对象替换老对象,例如state.obj = { ...state.obj,newProp: 1 }
。
Mutation必须是同步函数
mapMutations辅助函数
import { mapMutations } from "vuex";
export default {
//..
methods: {
...mapMutations([
"increment" // 映射 this.increment() 为 this.$store.commit("increment")
]),...mapMutations({
add: "increment" // 映射 this.add() 为 this.$store.commit("increment")
})
}
// ...
}
注册actions
const store = new Vuex.Store({
state: {
count: 0
},mutations: {
increment: function(state) {
state.count++;
}
},actions: {
increment: function(context) {
setInterval(() => context.commit("increment"),1000);
}
}
})
分发actions
// 分发
this.$store.dispatch("increment");
// 以载荷形式分发
store.dispatch("incrementN",{ n: 10 });
// 以对象形式分发
store.dispatch({ type: "incrementN",n: 10 });
mapActions辅助函数
import { mapActions } from "vuex";
export default {
//..
methods: {
...mapActions([
"incrementN" //映射 this.incrementN() 为 this.$store.dispatch("incrementN")
]),...mapActions({
add: "incrementN" //映射 this.add() 为 this.$store.dispatch("incrementN")
})
}
// ...
}
组合Action
// ...
actions: {
actionA: function({ commit }) {
return new Promise((resolve,reject) => {
setTimeout(() => {
commit("someMutation");
resolve();
},1000)
})
}
}
// ...
// 在触发Actions时
// ...
store.dispatch("actionA").then(() => {
// ...
})
// ...
// 在另外一个 action 中
// ...
actions: {
// ...
actionB: function({ dispatch,commit }) {
return dispatch("actionA").then(() => {
commit("someOtherMutation");
})
}
}
// ...
// 使用 async/await
// 当然此时getData()和getOtherData()需要返回Promise
actions: {
actionA: async function({ commit }) {
commit("gotData",await getData());
},actionB: async function({ dispatch,commit }) {
await dispatch("actionA");
commit("gotOtherData",await getOtherData());
}
}
// ...
模块分割
const moduleA = {
state: () => ({ /* ... */ }),mutations: { /* ... */ },actions: { /* ... */ },getters: { /* ... */ }
}
const moduleB = {
state: () => ({ /* ... */ }),actions: { /* ... */ }
}
const store = new Vuex.Store({
modules: {
a: moduleA,b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
模块的局部状态
const moduleA = {
state: { count: 0 },mutations: {
increment: function(state) {
// state 模块的局部状态
state.count++;
}
},getters: {
doubleCount: function(state) {
return state.count * 2
},sumWithRootCount: function(state,getters,rootState) {
return state.count + rootState.count;
}
}
}
const moduleA = {
// ...
actions: {
incrementIfOddOnRootSum: function({ state,commit,rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit("increment");
}
}
}
}
命名空间
const store = new Vuex.Store({
modules: {
account: {
namespaced: true,// 模块内容(module assets)
state: () => ({ ... }),// 模块内的状态已经是嵌套的了,使用 `namespaced` 属性不会对其产生影响
getters: {
isAdmin: function() { ... } // -> getters['account/isAdmin']
},actions: {
login: function() { ... } // -> dispatch('account/login')
},mutations: {
login: function() { ... } // -> commit('account/login')
},// 嵌套模块
modules: {
// 继承父模块的命名空间
myPage: {
state: () => ({ ... }),getters: {
profile: function() { ... } // -> getters['account/profile']
}
},// 进一步嵌套命名空间
posts: {
namespaced: true,state: () => ({ ... }),getters: {
popular: function() { ... } // -> getters['account/posts/popular']
}
}
}
}
}
})
modules: {
foo: {
namespaced: true,getters: {
// 在这个模块的 getter 中,`getters` 被局部化了
// 你可以使用 getter 的第四个参数来调用 `rootGetters`
someGetter(state,rootState,rootGetters) {
getters.someOtherGetter // -> "foo/someOtherGetter"
rootGetters.someOtherGetter // -> "someOtherGetter"
},someOtherGetter: state => { /* ... */ }
},actions: {
// 在这个模块中, dispatch 和 commit 也被局部化了
// 他们可以接受 `root` 属性以访问根 dispatch 或 commit
someAction({ dispatch,rootGetters }) {
getters.someGetter // -> "foo/someGetter"
rootGetters.someGetter // -> "someGetter"
dispatch("someOtherAction") // -> "foo/someOtherAction"
dispatch("someOtherAction",null,{ root: true }) // -> "someOtherAction"
commit("someMutation") // -> "foo/someMutation"
commit("someMutation",{ root: true }) // -> "someMutation"
},someOtherAction(ctx,payload) { /* ... */ }
}
}
}
{
actions: {
someOtherAction({ dispatch }) {
dispatch("someAction")
}
},modules: {
foo: {
namespaced: true,actions: {
someAction: {
root: true,handler(namespacedContext,payload) { /* ... */ } // -> "someAction"
}
}
}
}
}
// ...
computed: {
...mapState({
a: state => state.some.nested.module.a,b: state => state.some.nested.module.b
})
},methods: {
...mapActions([
"some/nested/module/foo",// -> this["some/nested/module/foo"]()
"some/nested/module/bar" // -> this["some/nested/module/bar"]()
])
}
// ...
// ...
computed: {
...mapState("some/nested/module",{
a: state => state.a,b: state => state.b
})
},methods: {
...mapActions("some/nested/module",[
"foo",// -> this.foo()
"bar" // -> this.bar()
])
}
// ...
// ...
import { createNamespacedHelpers } from "vuex"
const { mapState,mapActions } = createNamespacedHelpers("some/nested/module")
export default {
computed: {
// 在 `some/nested/module` 中查找
...mapState({
a: state => state.a,methods: {
// 在 `some/nested/module` 中查找
...mapActions([
"foo","bar"
])
}
}
// ...
import Vuex from "vuex";
const store = new Vuex.Store({ /* 选项 */ })
// 注册模块 `myModule`
store.registerModule("myModule",{
// ...
})
// 注册嵌套模块 `nested/myModule`
store.registerModule(["nested","myModule"],{
// ...
})
https://github.com/WindrunnerMax/EveryDay
https://vuex.vuejs.org/zh/
https://www.jianshu.com/p/1fdf9518cbdf
https://www.jianshu.com/p/29467543f77a
https://juejin.cn/post/6844903624137523213
https://segmentfault.com/a/1190000024371223
https://github.com/Hibop/Hibop.github.io/issues/45