项目地址在 https://github.com/Hard-workingrookie/todoList_vuex
组件之间共享数据的方式
父向子传值: v-bind 属性绑定
子向父传值: v-on 属性绑定
兄弟组件之间共享数据 :EventBus
- $on 接收数据的那个组件
- $emit 发送数据的那个组件
Vuex 是什么
Vuex
是实现正在组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享。
Vuex 的基本使用
安装 Vuex 依赖包
导入 Vuex 包
1 2
| import Vuex from 'vuex' Vue.use(Vuex)
|
创建 store 对象
1 2 3
| const store =new Vuex.Store({ state:{count:0} })
|
将 store 对象挂载到 vue 实例中
1 2 3 4 5 6
| new Vue({ el:'#app', render:h=>h(app), router, store })
|
使用 Mutation 变更 store 中的数据
1 2 3 4 5 6 7 8 9 10 11 12
| mutations: { add (state) { state.count++ }, sub (state) { if (state.count > 0) { state.count-- } } }
|
在页面使用
1 2 3
| addCount () { this.$store.commit('add') }
|
1 2 3
| subCount () { this.$store.commit('sub') }
|
mutations 带参传送
1 2 3
| addN (state, step) { state.count += step }
|
1 2 3 4
| addCount () { this.$store.commit('addN', 3) }
|
Mutation 触发
this.$store.commit()
是触发 mutation 第一种方式
第二种:
1
| import { mapMutations } from 'vuex'
|
1
| ...mapMutations(['add'])
|
带参:
1 2 3 4 5 6
| methods: { ...mapMutations(['add', 'addN']), addCount () { this.addN(3) } }
|
不要在 mutations 中执行异步操作。action 用于执行异步操作
Action
action 用于执行异步操作
触发 action
第一种方式
不带参
1 2 3 4 5 6 7
| actions: { addAsync (context) { setTimeout(() => { context.commit('add') }, 1000) } },
|
1
| this.$store.dispath('addAsync')
|
带参
1 2 3 4 5 6 7 8
| actions: { addAsync (context,step) { setTimeout(() => { context.commit('addN',step) }, 1000) } },
|
1
| this.$store.dispath('addAsync',5)
|
第二种方式
1.导入:
1
| import { mapAction } from 'vuex'
|
2.映射到当前组件的 methods 函数
1 2 3 4
| methods:{ ...mapAction(['addAsync','addNAsync']) }
|
Getter
Getter 用于对 store 中的数据进行加工处理形成新的数据。
1 2 3 4 5 6 7 8 9 10
| const store=new Vuex.Store({ state:{ count:0 }, getters:{ showNum:state=>{ return '当前最新的数量是【'+state.count+'】' } } })
|
使用 Getter 的第一种方式
this.$store.getters.名称
使用 Getter 的第二种方式
1
| import { mapGetters } from 'vuex'
|
1 2 3
| computed: { ...mapGetters(['showNum']) }
|
Modules
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| const moduleA = { state: () => ({ ... }), mutations: { ... }, actions: { ... }, getters: { ... } }
const moduleB = { state: () => ({ ... }), mutations: { ... }, actions: { ... } }
const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } })
store.state.a store.state.b
|
模块的局部状态
对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const moduleA = { state: () => ({ count: 0 }), mutations: { increment (state) { state.count++ } },
getters: { doubleCount (state) { return state.count * 2 } } }
|
对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState
1 2 3 4 5 6 7 8 9 10
| const moduleA = { actions: { incrementIfOddOnRootSum ({ state, commit, rootState }) { if ((state.count + rootState.count) % 2 === 1) { commit('increment') } } } }
|
对于模块内部的 getter,根节点状态会作为第三个参数暴露出来:
1 2 3 4 5 6 7 8
| const moduleA = { getters: { sumWithRootCount (state, getters, rootState) { return state.count + rootState.count } } }
|
在带命名空间的模块内访问全局内容
如果你希望使用全局 state 和 getter,rootState 和 rootGetters 会作为第三和第四参数传入 getter,也会通过 context 对象的属性传入 action。
若需要在全局命名空间内分发 action 或提交 mutation,将 { root: true } 作为第三参数传给 dispatch 或 commit 即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| modules: { foo: { namespaced: true,
getters: { someGetter (state, getters, rootState, rootGetters) { getters.someOtherGetter rootGetters.someOtherGetter }, someOtherGetter: state => { ... } },
actions: { someAction ({ dispatch, commit, getters, rootGetters }) { getters.someGetter rootGetters.someGetter
dispatch('someOtherAction') dispatch('someOtherAction', null, { root: true })
commit('someMutation') commit('someMutation', null, { root: true }) }, someOtherAction (ctx, payload) { ... } } } }
|
在带命名空间的模块注册全局 action
若需要在带命名空间的模块注册全局 action,你可添加 root: true,并将这个 action 的定义放在函数 handler 中。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| { actions: { someOtherAction ({dispatch}) { dispatch('someAction') } }, modules: { foo: { namespaced: true,
actions: { someAction: { root: true, handler (namespacedContext, payload) { ... } } } } } }
|
模块动态注册
在 store 创建之后,你可以使用 store.registerModule 方法注册模块:
1 2 3 4 5 6 7 8 9 10 11 12
| import Vuex from 'vuex'
const store = new Vuex.Store({ })
store.registerModule('myModule', { })
store.registerModule(['nested', 'myModule'], { })
|
之后就可以通过 store.state.myModule
和 store.state.nested.myModule
访问模块的状态。
模块动态注册功能使得其他 Vue 插件可以通过在 store 中附加新模块的方式来使用 Vuex 管理状态。例如,vuex-router-sync 插件就是通过动态注册模块将 vue-router 和 vuex 结合在一起,实现应用的路由状态管理。