一、核心原理
1.Vuex本质是一个对象,有两个属性,一个是install方法,一个是Store这个类。
2.install方法的作用是将store这个实例挂载到所有的组件上,注意是同一个store实例。
3.Store这个类拥有commit,dispatch这些方法,Store类里将用户传入的state包装成data,作为new Vue的参数,从而实现了state 值的响应式。
4.$store是挂载在Vue实例、即Vue.prototype中,在组件中可使用 this 访问原型上的属性 如 this.$store.state.count。
工作原理如图:
vuex.png
通过store.dispatch('increment')分发Action(可异步操作回调),通过Action 提交Mutation(只能同步更改数据),通过Mutation修改state里面的值
二、伪代码
state:{
conut:1
},
mutations:{
setDataMutation(state,payload){// 在大多数情况下,载荷payload 应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读
state.count+=payload.count
}
},
actions:{
setDataAction(context,data){
context.commit('setDataMutation',data)
}
}
this.store.dispatch('setDataAction',{count:2}).then(()=>{})
三、简化写法(辅助函数mapState、mapGetters 、mapMutations 、 mapActions)
为了减少代码量...
mapState
- 需要从 store 实例中读取状态时,并赋予computed计算属性时
computed:{
count:(){
return this.$store.state.count
}
}
- 使用 mapState
import { mapState } from 'vuex'
export default {
computed:mapState{
count:state => state.count
}
}
- 当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
- 与局部计算属性混合使用
computed: {
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
}
mapGetters
- store 的 getter,可以认为是 store 的计算属性,用来筛选store中符合某些条件的数据
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
- 使用getter
const store = createStore({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: (state) => {
return state.todos.filter(todo => todo.done)
}
}
})
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
- 使用mapGetters
mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
...mapGetters({
// 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
})
mapMutations
- mutation 需要store实例的commit方法触发
this.$store.commit('setDataMutation')
- 使用 mapMutations
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'setDataMutation', // 将 `this.setDataMutation()` 映射为 `this.$store.commit('setDataMutation')`
// `mapMutations` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
})
}
}
mapActions
-
在组件中分发Action:使用 this.$store.dispatch('xxx') 分发 action
-
使用mapActions
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'setDataAction', // 将 `this.setDataAction()` 映射为 `this.$store.dispatch('setDataAction')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
四、使用Module
作用:将全局数据按分类储存在不同模块中
- 开启namespace
// 在module中
export default {
namespaced: true,
// ...
}
import moduleA from './module/moduleA';
import moduleB from './module/moduleB';
export default new Vuex.Store({
modules: {
moduleA, moduleB,
},
// ...
}
// ...
computed: {
...mapState({
name: state => state.moduleA.text
}),
},
// ...
computed: {
...mapState('some/nested/module', {
a: state => state.a,
b: state => state.b
})
},
methods: {
...mapActions('some/nested/module', [
'foo', // -> this.foo()
'bar' // -> this.bar()
])
}
- createNamespacedHelpers 创建基于某个命名空间辅助函数。
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
export default {
computed: {
// 在 `some/nested/module` 中查找
...mapState({
a: state => state.a,
b: state => state.b
})
},
methods: {
// 在 `some/nested/module` 中查找
...mapActions([
'foo',
'bar'
])
}
}
访问根节点
- 模块内部的 state 是局部的,只属于模块本身所有。那么如果我们要想在模块中访问 store 根节点的数据 state,怎么办呢?
export default {
// ...
getters: {
// 注意:rootState必须是第三个参数
detail(state, getters, rootState) {
return state.text + '-' + rootState.name;
}
},
actions: {
callAction({state, rootState}) {
alert(state.text + '-' + rootState.name);
}
}
}
- 在带命名空间的模块内访问全局内容
modules: {
foo: {
namespaced: true,
getters: {
// 在这个模块的 getter 中,`getters` 被局部化了
// 你可以使用 getter 的第四个参数来调用 `rootGetters`
someGetter (state, getters, rootState, rootGetters) {
getters.someOtherGetter // -> 'foo/someOtherGetter'
rootGetters.someOtherGetter // -> 'someOtherGetter'
},
someOtherGetter: state => { ... }
},
actions: {
// 在这个模块中, dispatch 和 commit 也被局部化了
// 他们可以接受 `root` 属性以访问根 dispatch 或 commit
someAction ({ dispatch, commit, getters, rootGetters }) {
getters.someGetter // -> 'foo/someGetter'
rootGetters.someGetter // -> 'someGetter'
dispatch('someOtherAction') // -> 'foo/someOtherAction'
dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
commit('someMutation') // -> 'foo/someMutation'
commit('someMutation', null, { root: true }) // -> 'someMutation'
},
someOtherAction (ctx, payload) { ... }
}
}
}
网友评论