前言
这是我从事程序员这个职业以来发表的第一篇技术博客,其实这是我一直想做的事情,但是迟迟没有行动,今天终于开始了,写博客是一件双赢的事情,既巩固自己所学,又可以帮助他人,我相信自己会一直写下去,如有不对的地方也希望各位大佬多多指正。好了,下面开始进入正题。
Vuex理解
Vuex 是一个专为 Vue.js 应用程序开发的状态管理库,适用于多个组件共享状态的情况,Vuex起到了一个对组件状态进行集中式管理的作用。
Vuex的主要组成部分
我们一般会在src目录下创建一个store(或者vuex)文件夹,用来存放Vuex的几个组成模块,分别是:state、actions、mutation-types、mutations、getters、index。
State
state就是Vuex管理的状态对象,将所有需要共享的数据包裹在一个对象中暴露出去
state.js
/*
vuex管理的状态对象
*/
export default {
address:{}, // 地址信息对象
categorys:[], // 商品种类
shops:[], // 商铺列表
user:{}, // 登录的用户信息
}
下面就涉及到一个问题,组件中如何读取Vuex中的state状态呢?
- 首先在main.js中注册store选项,该 store 实例会注入到根组件下的所有子组件中,然后在子组件中就可以通过 this.$store.store.状态名 获取到Vuex中的状态数据
- 通过mapState辅助函数来读取,这种写法比较精炼,适用读取多个状态。
Actions
actions包含多个事件回调函数的对象,通过执行commit()来触发mutation的调用,间接更新状态(不直接更新状态的原因是mutation必须同步执行),可以包含异步代码(定时器、ajax请求等),action函数接收2个参数:({commit, state}, data)。 组件中分发action的2种方式:
- 通过 $store.dispatch('action名称',data) 的方式来分发action。
- 使用
mapActions辅助函数将组件的 methods 映射为store.dispatch调用(需要先在根节点注入store)
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
actions.js 异步action
// 异步获取食品分类列表
async getCategorys({commit}) {
const result = await reqCategorys()
if(result.code === 0){
const categorys = result.data
commit(RECEIVE_CATEGORYS,{categorys})
}
}
actions.js 同步action
// 同步保存用户信息
saveUser({commit},user){
commit(SAVE_USER,{user})
},
Mutations
mutations包含多个直接更新state的方法的对象,由action中的commit()触发调用,mutation接收2个参数,state和commit函数传递过来的对象数据,mutation必须是同步函数。
mutations.js
[RECEIVE_ADDRESS](state,{address}){
state.address = address
},
[RECEIVE_CATEGORYS](state,{categorys}) {
state.categorys = categorys
},
Mutation-types
mutation事件类型的常量名称模块。使用常量名称模块主要有以下2个好处:
- 常量放在单独的文件中可以让你的代码合作者对整个 app 包含的 mutation 一目了然
- actions和mutations中用到的事件类型直接引入常量名称模块,这样不至于写错
Getters
包含多个基于state的getter计算属性的对象,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算,getter接受 state 作为其第一个参数。 三种组件中访问方式:
- 通过属性访问
getters.js
// 购物车商品总数量
totalCount (state) {
return state.shopCart.reduce((pre,food) => pre + food.count,0)
},
- 通过方法访问 可以通过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查询时非常有用。注意,getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。
getters.js
getters: {
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
- mapGetters辅助函数
Module
当应用程序的功能模块比较多时,所有的状态都集中到一个对象,这样store对象就变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module) 。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
const moduleA = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: () => ({ ... }),
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
Index
Vuex的核心管理对象store对象模块,将Vuex的各组成部分引入,并声明Vue使用上Vuex
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import actions from './actions'
import mutations from './mutations'
import getters from './getters'
Vue.use(Vuex)
export default new Vuex.Store({
state,
actions,
mutations,
getters
})