Vue使用Vuex一步步封装并使用store全过程
目录
- 一、安装Vuex依赖
- 二、一步步封装store
- 1. main.js中全局引入store仓库(下一步创建)
- 2. this.$store
- 3. this.$store.state
- 4. this.$store.getters(this. $store.state的升级)
- 5. this.$store.commit(‘mutations’)
- 6. this.$store.dispatch(‘actions’)(this. $store.commit(‘mutations’)的升级)
- 7. strict严格模式
- 三、modules 模块化
- 四、使用仓库
- 1. 无map系列
- 2. map映射系列
- 3. 扩展
- 3. 总结
- 最后
一、安装Vuex依赖
cnpm install vuex --save
二、一步步封装store
1. main.js中全局引入store仓库(下一步创建)
import store from './store' //引入store new Vue({ el: '#app', router, store, //挂载store,this将自动生成$store属性 template: '<App/>', components: { App } })
挂载store,this将自动生成$store属性
2. this.$store
创建store仓库:习惯在src下创建store文件夹,再创建index.js,内容:
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store(); export default store;
此时你已经有了一个空的store全局仓库,没有任何功能,但可以在任何vue实例下使用 this.$store 去访问它。
- store使用范围均是可以全局使用;
- let a=1; {a:a}.a 的缩写是 {a}.a,即当字典的键和值命名一样时,可以省略只写a
- state、getters、mutations、mutations均是Vuex封装好的特殊变量,以下声明的功能变量均是这些名字,一个好处是store挂载该功能时可以简写(如3-1,本例均如此)。当然你也可直接在store中写功能(如3-2)。
3. this.$store.state
给store仓库读取数据功能:state
/********* 3-1 **********/ import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const state={ //要设置的全局访问的state对象,赋予初始属性值 themeColor: {val:'blue',opacity:false}, changeThemeCount:0, cache:'' }; const store = new Vuex.Store({ state }); export default store;
此时你的store仓库已经有了存取数据的功能,可以用 this.$store.state.themeColor 等数据了。
下面是第二种写法
/********* 3-2 **********/ import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const store = new Vuex.Store({ state:{ //要设置的全局访问的state对象,赋予初始属性值 themeColor: {val:'blue',opacity:false}, changeThemeCount:0, cache:'' } }); export default store;
4. this.$store.getters(this. $store.state的升级)
给state功能升级,让他拥有计算能力(类似vue中的computed方法):getters:
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const state={ //要设置的全局访问的state对象,赋予初始属性值 themeColor: {val:'blue',opacity:false}, changeThemeCount:0, cache:'' }; const getters = { //实时监听state值的变化(最新状态) getThemeColor(state) { //定义函数,返回处理过的val,命名最好有代表性 let hour = new Date().getHours(); // 如果白天则主题色不透明,反之 state.themeColor.opacity = 8 <= hour && hour <= 20; return state.themeColor } }; const store = new Vuex.Store({ state, // 挂载存取数据功能 getters //挂载数据计算功能 }); export default store;
此时使用 this.$store.getters.getThemeColor 获取颜色,将自动根据时间的不同自动设置主题是否有透明的效果
5. this.$store.commit(‘mutations’)
给store仓库使用函数功能(只为操作state数据):mutations - 同步
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const state={ //要设置的全局访问的state对象,赋予初始属性值 themeColor: {val:'blue',opacity:false}, changeThemeCount:0, cache:'' }; const getters = { //实时监听state值的变化(最新状态) getThemeColor(state) { //定义函数,返回处理过的val,命名最好有代表性 let hour = new Date().getHours(); // 如果白天则主题色不透明,反之 state.themeColor.opacity = 8 <= hour && hour <= 20; return state.themeColor } }; const mutations = { //自定义改变state初始值的方法,这里面的参数除了state之外还可以再传额外的参数(变量或对象); clearCatch(state) { state.cache = ""; state.changeThemeCount= 0; }, setThemeColor(state,color,opacity){ state.themeColor.val = color; state.themeColor.opacity = opacity; state.changeThemeCount++; } }; const store = new Vuex.Store({ state, // 挂载存取数据功能 getters, //挂载数据计算功能 mutations // 挂载函数功能 }); export default store;
此时可以使用 this.$store.commit(‘setThemeColor’,‘grey’,‘1’) 了(注意第一个参数是函数名,不是传参给state的,state自己会传,后两个才是对应传参)。
可以主动设置主题色和透明度,操作是同步的,即如果你在同一个组件连续调用多次setThemeColor函数,获取仓库中state.changeThemeCount的值是一样的,下面介绍异步函数。
6. this.$store.dispatch(‘actions’)(this. $store.commit(‘mutations’)的升级)
给store仓库的函数commit功能升级(只为异步操作mutations中的函数):actions - 异步
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const state={ //要设置的全局访问的state对象,赋予初始属性值 themeColor: {val:'blue',opacity:false}, changeThemeCount:0, cache:'' }; const getters = { //实时监听state值的变化(最新状态) getThemeColor(state) { //定义函数,返回处理过的val,命名最好有代表性 let hour = new Date().getHours(); // 如果白天则主题色不透明,反之 state.themeColor.opacity = 8 <= hour && hour <= 20; return state.themeColor } }; const mutations = { //自定义改变state初始值的方法,这里面的参数除了state之外还可以再传额外的参数(变量或对象); clearCatch(state) { state.cache = ""; state.changeThemeCount= 0; }, setThemeColor(state,color,opacity){ state.themeColor.val = color; state.themeColor.opacity = opacity; state.changeThemeCount++; } }; const actions = { //自定义触发mutations里函数的方法,context与store 实例具有相同方法和属性 setThemeColorAction(context,color,opacity){ context.commit('setThemeColor',color,opacity); } }; const store = new Vuex.Store({ state, // 挂载存取数据功能 getters, //挂载数据计算功能 mutations, // 挂载函数功能 actions, // 挂载异步函数 }); export default store;
此时可以使用 this.$store.dispatch(‘setThemeColorAction’,‘grey’,‘1’) 了(注意第一个参数是函数名,不是传参给context的,context自己会传,后两个才是对应传参)。
可以主动设置主题色和透明度,操作是异步的,即如果你在同一个组件连续调用多次setThemeColorAction函数,获取仓库中state.changeThemeCount的值就不是一样的。
7. strict严格模式
export default new Vuex.Store({ strict: true, state: { ... }, ... }
此模式下所有的状态变更(即更新state)必须使用mutation(commit),如果在组件中直接修改state则会报错。这样的好处是所有的state的更新都体现在仓库中,整改方便;使用devTools调试工具时可以跟踪到状态的修改。
三、modules 模块化
第二个模块介绍了store仓库的四个功能:state、getters、mutations和actions,下面介绍第五个功能:modules。
- 当项目比较大时,一个store中数据会非常多而复杂,不易管理。此时便可建多个“子仓库”,分别对应不同模块做数据的读取和操作。
- 注意主仓库还是那一个,只要把他的“子仓库”放在主仓库的modules下即可。
- 子仓库看着很像仓库,其实它并不是store的实例,不是仓库(new Vuex.Store()实例化后的对象才是仓库),只是一个普通js对象(字典)。
1、在store下新建modules文件夹,在modules下新建home.js“子仓库”。
即home.js只管主页下的数据(一般不要分的太细,最多一个页面一个仓库管简洁),下面是home.js代码
//home.js const state={ users:[] //存访问该页面的所有用户 }; const getters={ getUsers(state){ //获取访问该页面的所有用户 // 对数据清理-除去脏数据 if (state.users.includes('*')) delete state.users['*'] return state.users; } }; const mutations={ addUser(state,name){ //增加访问用户 state.collects.push(name) } }; const actions={ invokeAddUser(context,name){ //触发mutations里面的addUser,传入数据形参name对应到users context.commit('addUser',name); } }; // 注意和仓库的区别 const store = { // namespaced用于在全局引用此文件里的方法时标识这一个的文件名,使得让人明白这些数据来自哪个仓库 // 即当你需要在别的文件里面使用子仓库(mapStates、mapGetters、mapActions)时,里面的方法需要注明来自哪一个模块的方法 namespaced:true, state, getters, mutations, actions } export default store;
2.“子仓库”创建完成,要让主仓库引用它:
import Vue from 'vue'; import Vuex from 'vuex'; import home from './modules/home.js' Vue.use(Vuex); const state={ //要设置的全局访问的state对象,赋予初始属性值 themeColor: {val:'blue',opacity:false}, changeThemeCount:0, cache:'' }; const getters = { //实时监听state值的变化(最新状态) getThemeColor(state) { //定义函数,返回处理过的val,命名最好有代表性 let hour = new Date().getHours(); // 如果白天则主题色不透明,反之 state.themeColor.opacity = 8 <= hour && hour <= 20; return state.themeColor } }; const mutations = { //自定义改变state初始值的方法,这里面的参数除了state之外还可以再传额外的参数(变量或对象); clearCatch(state) { state.cache = ""; state.changeThemeCount= 0; }, setThemeColor(state,color,opacity){ state.themeColor.val = color; state.themeColor.opacity = opacity; state.changeThemeCount++; } }; const actions = { //自定义触发mutations里函数的方法,context与store 实例具有相同方法和属性 setThemeColorAction(context,color,opacity){ context.commit('setThemeColor',color,opacity); } }; const store = new Vuex.Store({ state, // 挂载存取数据功能 getters, //挂载数据计算功能 mutations, // 挂载函数功能 actions, // 挂载异步函数 modules:{ // 挂载子仓库 home } }); export default store;
此时便有了第一个“子仓库”了!
四、使用仓库
1. 无map系列
适合使用场景较少:
建好仓库,组件中直接使用state、getters、mutations、actions:
this.$store.state.*
this.$store.getters.*
this.$store.commit.*
this.$store.dispatch.*
2. map映射系列
适合使用场景频繁:
使用mapGetters、mapActions 和 mapStates之前需要import导入:
import {mapState,mapGetters,mapActions} from 'vuex';
使用ES6新语法-超引用,将某个功能下的数据或方法全部映射出来以供使用,下面是mapState、mapGetters、mapActions的例子:
//这里的...是超引用,映射内容,可以写在computed下、methods下等(一般放在开头) // 直接从库中取值 - 将库里的users值返回给字典中的users并映射给this组件 ...mapState({ users:state=>state.home.users }), // 使用计算属性 - 将库里的users计算后的值返回给字典中的users并映射给this组件 ...mapGetters('home',{ users:'getUsers' //获取清理后的数据 //由于home仓库 namespaced:true,所以第一个参数作为标识 // 不使用标识访问的是主仓库 }) // 使用异步函数 - 以数组中的函数名,从库中对应的函数映射给this组件以供使用 ...mapActions('home',['invokeAddUser']) // 有某个组件 <span @click='invokeAddUser(name)'></span> // 或者直接使用 this.invokeAddUser(name)
3. 扩展
mapState映射的三种写法
computed: mapState({ // 箭头函数可使代码更简练 count: state => state.count, // 传字符串参数 'count' 等同于 `state => state.count` countAlias: 'count', // 为了能够使用 `this` 获取局部状态,必须使用常规函数 countPlusLocalState (state) { return state.count + this.localCount } }) 2、当映射的计算属性的名称与state的子节点名称相同时, 我们也可以给 mapState传一个字符串数组。 computed: mapState([ // 数组 "count" ]) 3、仓库中action的第二种接收参数 const actions = { //自定义触发mutations里函数的方法,{commit}与store 实例具有相同方法和属性 setThemeColorAction({commit},color,opacity){ commit('setThemeColor',color,opacity); } };
3. 总结
1、Vuex 是一个专门为 Vue.js 应用所设计的集中式状态管理架构。它借鉴了 Flux 和 Redux 的设计思想,但简化了概念,并且采用了一种为能更好发挥 Vue.js 数据响应机制而专门设计的实现。
2、Vuex 的四个核心概念分别是:
The state tree
:Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。Getters
: 用来从 store 获取 Vue 组件数据。Mutators
: 事件处理器用来驱动状态的变化。Actions
: 可以给组件使用的函数,以此用来驱动事件处理器 mutations
3、Vuex 应用中数据的流向(Vuex 官方图)
数据流都是单向的组件能够调用 actionaction 用来派发 Mutation只有 mutation 可以改变状态store 是响应式的,无论 state 什么时候更新,组件都将同步更新
最后
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。