[toc]
Vuex
-
Vuex是一个为Vue.js应用程序开发的状态管理模式
- 采用集中存储管理应用的所有组件的状态
-
管理什么状态?
- 多个页面间共享的,如用户登录状态,用户名称,头像,地理位置信息,商品的收藏,购物车中的商品
//router/index.js import Vuex from 'vuex' Vue.use(Vuex) // 安装插件,会去调用插件的install方法 const store = new Vuex.store({ state: { counter: 0 }, mutations: { increment(state){ //默认有一个参数state state.counter++ }, decrement(state){ state.counter-- } }, actions: { }, getters: { }, modules: { } }) export default store //组件中调用 <button @click="add"></button> methods: { add(){ this.$store.commit('increment') } }
Vuex是一个全局的单例模式
Vuex核心概念
-
State
- 单一状态树:所有状态信息都保存在一个store中
-
Getters
当需要从store中获取一些state变异后的状态时使用
const store = new Vuex.store({ state: { counter: 0 }, getters: { powerCounter(state){ return state.counter**2 } } } //使用 {{$state.getters.powerCounter}}
const store = new Vuex.store({ state: { counter: 0, students: [ {name: 'aaa', age:10}, {name: 'bbb', age:20}, {name: 'ccc', age:30}, {name: 'ddd', age:40}, ] }, getters: { powerCounter(state){ return state.counter**2 }, //获取大于20岁的学生 more20Stus(state){ return state.students.filter(s=>s.age>20) }, //获取大于20岁的学生的个数 (getters可以作为参数传入) more20StusLen(state, getters){ return getters.more20Stus.length }, //如果想自定义传入age moreAgeStus(state){ return function(age){ return state.students.filter(s=>s.age>age) } } } } //使用 {{$state.getters.powerCounter}} {{$state.getters.more20Stus}} {{$state.getters.more20StusLen}} {{$state.getters.moreAgeStus(30)}}
-
Mutation
Vuex的store状态更新的唯一方式:提交Mutation
-
Mutation主要包括两部分
- 字符串的事件类型(type)
- 一个回调函数(handler),该回调函数的第一个参数就是state
-
传递参数
- 参数被称为mutation的载荷(payload)
//router/index.js import Vuex from 'vuex' //普通提交风格 Vue.use(Vuex) // 安装插件,会去调用插件的install方法 const store = new Vuex.store({ state: { counter: 0 }, mutations: { incrementCount(state, count){ state.counter+=count } } }) export default store //组件中调用 <button @click="add"></button> methods: { add(){ this.$store.commit('incrementCount', count) } } //特殊提交风格 const store = new Vuex.store({ state: { counter: 0 }, mutations: { incrementCount(state, payload){ state.counter += payload.count } } }) export default store //组件中调用 <button @click="add"></button> methods: { add(){ this.$store.commit({ type: 'incrementCount', count }) } }
-
mutation响应规则
- 提前在store中初始化好所需的属性
- 当给state的对象添加新属性时,使用Vue.set(obj, key, value),当删除属性时,使用Vue.delete(obj, key)
-
Mutation常量
//router/index.js import Vuex from 'vuex' import {INCREMENT, DECREMENT} from 'mutation-types' Vue.use(Vuex) // 安装插件,会去调用插件的install方法 const store = new Vuex.store({ state: { counter: 0 }, mutations: { [INCREMENT](state){ //默认有一个参数state state.counter++ }, [DECREMENT](state){ state.counter-- } }, }) export default store //组件中调用 import {INCREMENT} from 'mutation-types' <button @click="add"></button> methods: { add(){ this.$store.commit(INCREMENT) } } //mutation-types.js export const INCREMENT = 'increment' export const DECREMENT = 'decrement'
-
VueX要求Mutation中的方法必须是同步方法
- 主要原因是使用devtools时,devtools可以帮助我们捕捉mutation的快照
- 但是如果是异步操作,那么devtools不能很好地追踪这个操作什么时候会被完成
- 不要在mutation中进行异步操作
-
Action
-
Action类似于Mutation,是用来代替Mutation进行异步操作的
//router/index.js import Vuex from 'vuex' import {INCREMENT, DECREMENT} from 'mutation-types' Vue.use(Vuex) // 安装插件,会去调用插件的install方法 const store = new Vuex.store({ state: { info: {name: 'aaa', age: 18} }, mutations: { updateInfo(state){ state.info = 'bbb' } }, actions: { aupdateInfo(context){ //默认携带context参数 return new Promise((resolve, reject)=>{ setTimeout(()=>{ context.commit('updateInfo') }, 1000) resolve() }) } } }) export default store //组件中调用 <button @click="add"></button> methods: { update(){ this.$store.dispatch('aupdateInfo').then(()=>{console.log('修改完成')}) //不带参数 this.$store.dispatch('aupdateInfo', payload) //携带参数 } }
-
-
Module
- Vue使用单一状态树,这样当应用变得复杂时,store对象可能变得非常臃肿,为了解决这个问题,Vuex允许我们将store分割成模块,每个模块拥有自己的state、mutations、actions、getters等