Vuex是什么

Vuex是为Vue.js提供的状态管理模式/工具。

官方文档

https://vuex.vuejs.org/zh/api/#replacestate

描述

当多个组件共享状态时,会出现1.多个视图依赖同一个状态 2.不同视图的行为会改变同一个状态。这种复杂庞大的系统如果采用props和emit事件的方式进行父子组件传值会导致代码很难维护,兄弟组件的传值更是不方便(bus中央事件总线和父组件中转)

将共享状态抽离,进行集中管理,我们的组件树构成一个巨大的‘视图’,无论树的哪个位置,都能获取状态或触发行为改变状态。这就回到了Vuex。

原理
核心内容
1
state,getter,mutation,action, module(模块)
安装
1
cnpm install vuex --save
引入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state,
getters,
mutations,
actions
})
export default store

// main.js
import store from 'store.js'
new Vue({
store
。。。
})
// 挂载后组件内就可以用this.$store。对于js文件,需要引入store,然后使用store,不能用this。
使用
集中时的使用
1
2
3
4
5
6
// state定义
const state = {
name: '状态'
}
// state使用
this.$store.state.name
1
2
3
4
5
6
7
8
9
10
11
12
13
// mutation定义
const mutations = {
changeName(state, payload) {
state.name = payload || '改变状态'
}
}
// mutation提交
this.$store.commit('changeName')
this.$store.commit('changeName','payload')
this.$store.commit({
type: 'changeName',
payload: '此时mutation里接收的第二个参数payload是整个对象'
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 规定mutations里不能异步操作,虽然不会报错,但会影响调试工具及状态追踪等,还是按规定来,用actions异步操作,提交mutation来更改状态
// actions定义
const actions = {
commitMutations(context, payload) {
// context对象可以看作就是store的拷贝
// 可以获取state
let name = context.state.name
// 提交mutations
context.commit('changeName')
}
}
// actions触发
this.$store.dispatch('commitMutations')
this.$store.dispatch('commitMutations','payload')
this.$store.dispatch({
type: 'commitMutations',
payload: '此时actions里接收的第二个参数payload是整个对象'
})
1
2
3
4
5
6
// getters,可以理解为一个计算属性,可以处理状态并缓存,当处理状态需要的依赖改变时才会重新计算
const getters = {
newName: state => state.name+1
}
// 使用
this.$store.getters.newName
模块时的使用
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
// module.js
const state = {name: 'module'}
export default {
namespaced: true, // ?
state
}

// 自动导入modules模块,挂载
const module = require.context('./module', true, /\.js$/) // webpack的一个api,第一个参数是路径,第二个参数是是否匹配子目录,第三个是匹配什么文件
let obj = {}
module.keys().forEach(item => {
const keys = item.replace(/\.\/|\.js/g, '') // 得到module
let last = keys.split('/')[keys.split('/').length-1] // 最后一级文件夹的名字
obj[last] = module[item].default
})

let store = new Vuex.Store({
modules: {
...obj
}
})

// 使用
this.$store.state['module'].name
this.$store.commit('module/changeName', {payload:'payload'})
this.$store.dispatch('module/commitMutations', {payload:'payload'})
...mapActions('module', {
actionsFunc: 'commitMutations'
})
this.actionsFunc({payload:'payload'})
vuex辅助函数的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// mapState, mapGetters, mapMutations, mapActions
// mapState, mapGetters用在computed里,mapMutations, mapActions用在methods里最好
computed: {
...mapState({
name: 'name'
}),
...mapGetters({
newName: 'newName'
})
},
methods: {
...mapActions([
'commitMutations'
]),
...mapMutations([
'changeName'
])
},
mounted() {
this.changeName('d')
this.commitMutations('c')
// this.$store.commit('changeName','d')
// this.$store.dispatch('commitMutations','c')
}
mutation-type

一种复杂项目的优化代码可维护性的方式,我暂时不喜欢用

应用

列表封装,每个列表页配置一个状态管理module,由封装的组件去触发

问题

vuex 存储状态 刷新丢失问题 优化,1.vue-along插件,2.localStorage(不建议,小数据干脆直接用localstorage存得了),3.刷新就重新请求

1
2
3
4
window.addEventListener("beforeunload",()=>{
this.$store.state.media.openid = 88833888
localStorage.setItem('stateData', JSON.stringify(this.$store.state))
})
1
2
3
4
const data = JSON.parse(localStorage.getItem('stateData'))
if (data) {
this.$store.replaceState(Object.assign({}, this.$store.state, data))
}