vuex
1. 初始化 Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex) // 注册Vuex(Vue.use方法实际是调用了 Vuex 中的 install 方法)
const store = new Vuex.Store({
/* 【1】全局共享的数据 */
state: {},
/* 【2】修改 state 中的数据(不能写异步) */
mutations: {},
/* 【3】处理异步(不能修改 state 中数据的值 只能在 mutations 中修改) */
actions: {},
/* 【4】getter(和计算属性的功能差不多) */
getters: {},
/* 【5】模块化数据 */
modules: {}
})
new Vue({
el: '#app',
store
})
2. Vuex 新特性
2.1 Vuex 中 state 特性
-
state
作用:共享数据的定义state: { count:0 }
-
.vue 文件中使用
// 方法一 this.$store.state.count // 方法二(辅助函数) import { mapState } from 'vuex' computed:{ ...mapState(['count']) } // 使用 this.count
2.2 Vuex 中 mutations 特性
-
mutations
作用:修改 state 中数据(不能写异步方法,异步方法在actions中写)mutations: { // 参数1:state 为共享数据 // 参数2:payload 为载荷参数 setCount(state, payload){ state.count += payload } }
-
.vue 文件中使用
// 方法一 this.$store.commit(mutations中修改state中数据方法, 载荷参数) this.$store.commit('setCount', 2) // 方法二(辅助函数) import { mapMutations } from 'vuex' methods: { ...mapMutations(['setCount']) } // 调用 mutations 中方法 this.setCount(2)
2.3 Vuex 中 actions 特性
-
actions
作用:mutations中方法只能同步处理数据,不能写异步方法,actions中可以写异步方法actions: { // 参数1:context 执行的上下文对象(相当于组件中 this.$store store 的运行实例) // 参数2:payload 为载荷参数 getCount(context, payload) { // 定时器中函数为异步函数 setTimeout(() => { context.commit('setCount', payload) }, 1000) // 或接口请求获取数据 - 异步 } }
-
【注意】actions 中方法不能修改数据,通过调用 mutations 修改数据
-
.vue 文件中使用
// 方法一 this.$store.dispath(actions中异步方法名称, 载荷参数) this.$store.dispath('getCount', 2) // 方法二(辅助函数) import { mapActions } from 'vuex' methods: { ...mapActions(['getCount']) } // 调用该异步方法 this.getCount(2) // 调用 actions 中方法
2.4 Vuex 中 getters 特性
-
getters
作用:包装处理(可以说是 vuex 中计算属性)state: { list: [12,2,56,1,545,12,23,5,98], count: 0 }, getters: { showCount: (state) => state.count, showList: (state) => state.list.filter(item => item % 2 === 0 }) }
-
.vue 文件中使用
// 方法一 this.$store.getters.count // 方法二(辅助函数) import { mapGetters } from 'vuex' computed: { ...mapGetters(['showCount', 'showList']) } // 使用 this.showCount this.showList
2.5 Vuex 中 modules 特性(模块化)
-
modules
作用:避免共享数据太多,全部在一个对象中,造成代码臃肿,维护性差modules: { /**** 定义模块:可以定义多个模块,每个模块中都有 state、mutations、actions、getters ****/ // 【模块1】(modules1 模块名自命名) modules1: { state: { count: 10 }, mutations: { setData(state) {……} }, actions: { // context: 有属性 state、commit、rootState setData(context) {……} }, getters: { // rootState 根节点状态 count: (state, getters, rootState) => state.count } }, // 【模块2】 modules2: { nameSpaced: true, // 命名空间(模块拥有高度封闭性) state: { number: 20 }, mutations: {}, actions: {}, getters: {} } }
【注意】
- 模块的局部状态,对于模块内部的
mutation
和getter
,接收的第一个参数是模块的局部状态对象 - 对于模块内部的
action
, 局部状态通过context.state
暴露出来,根节点状态则为context.rootState
- 对于模块内部的
getter
, 根节点状态会作为第三个参数暴露出来
- 模块的局部状态,对于模块内部的
-
.vue 文件中使用
/* 【方法一】 */ this.$router.state.模块名称.state中属性名 // 【注意】模块名称后不用再写state,直接写state中属性即可 this.$router.state.modules1.state.count // × this.$router.state.modules1.count // √ this.$router.state.modules2.number /* 【方法二】(辅助函数) */ // 1.在 store 的 js 文件中根级别 getters 中获取模块化的数据 const store = new Vuex.Store({ state: {}, mutations: {}, actions: {}, getters: { showModulesCount: () => state.modules1.count, showModulesNumber: () => state.modules2.number }, modules: { …… // 模块化代码(见上) } }) // 2.借助 mapGetters 取模块化中数据 import { mapGetters } from 'vuex' computed: { ...mapGetters(['showModulesCount', 'showModulesNumber']) } // 3.使用该 getters 数据 this.showModulesCount this.showModulesNumber
2.6 Vuex 中模块化命名空间 nameSpaced
-
命名空间由来
默认情况:模块内部的 mutation 、action 和 getter 是注册在 全局命名空间 的,这样使得多个模块能够对同一 mutation 或 action 作出响应。
/******** 代码演示说明 ********/ // 模块 modules: { modules1: { state: { count: 10 }, mutations: { updateData(state) {……} } } } // 调用模块中修改 state 中数据的方法 import { mapMutations } from 'Vuex' methods: { ...mapMutations(['updateData']) } // 使用方法 this.$store.commit('updateData') // 【总结】和不用模块化时调用没有什么不同(方法在子模块中,但仍可以通过调用全局方法的方式调用)
想要:保证内部模块的高封闭性,可以使用
nameSpaced: true
进行设置,使当前模块变为带有命名空间的模块。 -
命名空间书写位置:
模块名称对象中直接属性 nameSpaced (具体见 2.5 模块2 modules2 中 nameSpaced 书写位置)
拥有命名空间的模块中 mutations、actions、getters 调用
-
命名空间模块中
mutations
在 .vue 文件中使用【区别】其实就是加上模块路径
// 模块代码 modules: { modules1: { nameSpaced: true, // 【重点】开启命名空间 state: { count: 10 }, mutations: { updateData(state) {……} }, actions: { updateDataAx(context) {……} }, getters: { showCount: (state) => state.count }, } }
- .vue 文件中使用
/* 【方法一】 */ this.$store.commit('模块名称/调用的mutations中方法名') this.$store.commit('modules1/updateData') /* 【方法二】借用辅助函数 mapMutations */ import { mapMutations } from 'Vuex' methods: { ...mapMutations(['模块名称/mutations中方法名']) ...mapMutations(['modules1/updateData']) } // 调用该方法 this.modules1/updateData() // × 该写法不不符合规定 this['modules1/updateData']() // √ /* 【方法三】借用辅助函数:创建基于某个命名空间的函数 */ import { createNamespacedHelpers } from 'vuex' const { 对应当前模块名称中的 mapMutations } = createNamespacedHelpers('模块名称') const { mapMutations } = createNamespacedHelpers('modules1') methods: { ...mapMutations(['mutations中方法名']) ...mapMutations(['updateData']) // 此处的 mapMutations 为 modules1 中的mapMutations } // 调用该方法 this.updateData()
【注意】模块不加命名空间时 -> 方法三不可用
-
此处省略 - 命名空间模块中
actions
、getters
在 .vue 文件中使用 -
命名空间模块中
mutations
actions
、getters
在 .vue 文件中使用完整代码/**** store 的js文件中 modules 中模块化代码 ****/ modules: { // 模块名称: modulesName modulesName: { namespaced: true, // 开启模块命名空间 state: { count: 0, num: 1, }, mutations: { updateCount(state, payload) { state.count += payload }, updateCount_copy(state, payload) { state.count += payload }, }, actions: { updateCountAx(context, payload) { setInterval(() => { context.commit('updateCount', payload) }, 2000) }, updateCountAx_copy(context, payload) { setInterval(() => { context.commit('updateCount_copy', payload) }, 2000) }, }, getters: { showCount: (state) => state.count, showNum: (state) => state.num, }, }, },
<!-- .vue 文件中使用 --> <template> <div> count值:{{ $store.state.modulesName.count }} getters中 count:{{ this["modulesName/showCount"] }} getters中 num:{{ showNum }} <br /> <button @click="clickPri">点击(原始方法)</button> <button @click="clickMap">点击(mapMutations)</button> <button @click="clickCreate">点击(createNamespacedHelpers)</button> </div> </template> <script> import { mapMutations, mapActions, mapGetters, createNamespacedHelpers, } from "vuex"; const { mapMutations: mapMutationsHelper, mapActions: mapActionsHelper, mapGetters: mapGettersHelper, } = createNamespacedHelpers("modulesName"); export default { computed: { ...mapGetters(["modulesName/showCount"]), ...mapGettersHelper(["showNum"]), }, methods: { ...mapMutations(["modulesName/updateCount"]), ...mapActions(["modulesName/updateCountAx"]), ...mapMutationsHelper(["updateCount_copy"]), ...mapActionsHelper(["updateCountAx_copy"]), // 【方法一】原始方法 clickPri() { this.$store.commit("modulesName/updateCount", 1); }, // 【方法二】借助 mapMutations 辅助函数 clickMap() { this["modulesName/updateCount"](2); }, // 【方法三】借助 createNamespacedHelpers 辅助函数,创建基于某个命名空间的函数 clickCreate() { this.updateCount_copy(3); }, }, }; </script>
模块化第三个参数 {root: true}
commit({
type:‘方法名’,
载荷})