Vuex状态管理
Vuex
Vuex
是一个专为Vue.js
应用程序开发的状态管理模式。它采用集中式管理应用的所有组件状态,并以相应的规则保证状态以一种可预测的方式发生变化。(类似于在前端的数据库,这里的数据存储在内存当中)
一、安装并配置
在项目的终端中写入如下的命令来安装Vuex
:
npm install vuex --save
配置main.js
文件,导入Vuex
:
import Vuex from 'vuex'
Vue.use(Vuex);
- 它竟然可以存多个组件的状态,当然要进行相应的一个配置,所以此时我们在项目的
src
目录下创建一个新的目录store
,并在内部准备一个配置文件index.js
import Vue from 'Vue'
import Vuex from 'Vuex'
Vue.use(Vuex);
// 公共state对象,存储所有组件的状态
const state = {
user: {
name:''
}
}
// 唯一取值的方法,计算属性
const getters = {
getUser(state) {
return state.user;
}
}
// 唯一可以修改state值的方法,同步阻塞
const mutations = {
updateUser(state, user) {
state.user = user;
}
}
// 异步调用mutations方法
const actions = {
asyncUpdateUser(user) {
// context 是上下文的意思 针对的就是这个 js 文件
// 且只能用 commit 进行调用mutations中的方法
// 当调用actions中的方法也是只能dispatch进行调用
context.commit('updateUser', user);
}
}
// 现在我们定义完了,此时就要将我们定义的内容暴露出去
export default new Vuex.Store({
state,
getters,
mutations,
actions
});
之后在main.js
中配置文件,再次引入我们刚刚写好的store
目录
import store from './store'
-
用户信息的添加和获取:
外界通过异步调用的方法,使用
dispatch()
调用添加,但是本质上还是使用的是mutations
中获取信息的方法(唯一修改方法)
二、解决浏览器刷新后Vuex
数据消失问题
问题描述
Vuex
的状态存储是响应式的,当Vue
组件从store
中读取状态的时候,若store
中的状态发送变化,那么相应的组件也会得到高效的更新,但是有一个问题就是vuex
的存储的数据只是在页面中的,相当于我们定义的全局变量,刷新之后,里面的数据就会恢复到初始状态。但是这种情况并不是我们所希望的
解决方案
监听页面是否刷新,如果页面刷新了,将state
对象存入到sessionStorage
中。页面打开之后,判断sessionStorage
中是否存在state
对象,如果存在,则说明页面是被刷新过的,将sessionStorage
中存的数据取出来给vuex
中的state
赋值,如果不存在,说明是第一次打开,则取vuex
中定义的state
初始值
代码实现:
因为我们在任何一个组件中进行刷新,我们都需要判断,但是我们不可能每一个组件中都设置判断,所以我们干碎就直接定义为全局的组件,故需要在根组件
App.vue
中设置监听刷新操作的事件
-
在
App.vue
中添加监听刷新事件export default { name: 'App', mounted() { window.addEventListener('unload', this.saveState); } , methods: { saveState() { window.sessionStorage.setItem('state', JSON.stringify(this.$store.state)) } } }
-
修改
store/index.js
中的state
const state = null != window.sessionStorage.getItem('state') ? JSON.parse(window.sessionStorage.getItem('state')) : { user: { name: '' } }
三、模块化
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store
对象就可能变得相当臃肿。为了解决以上的问题,Vuex
允许我们将store
分割成模块(module)
。每个模块拥有自己的state
、mutation
、action
、getter
、甚至是嵌套子模块一一从上至下进行同样方式的分割
-
创建
user
模块在
store
目录下创建一个名为modules
的目录并创建一个名为user.js
的文件,代码如下:const user = { state : { user: { name:'' } } // 唯一取值的方法,计算属性 getters : { getUser(state) { return state.user; } } // 唯一可以修改state值的方法,同步阻塞 mutations : { updateUser(state, user) { state.user = user; } } // 异步调用mutations方法 actions : { asyncUpdateUser(user) { // context 是上下文的意思 针对的就是这个 js 文件 // 且只能用 commit 进行调用mutations中的方法 // 当调用actions中的方法也是只能dispatch进行调用 context.commit('updateUser', user); } } } export default user;
注意:定义的
user.js
内部仍然是key : value
格式的,且最外层拿上const user = {}
包裹 -
修改
store/index.js
import Vue from 'Vue' import Vuex from 'Vuex' import user from './modules/user' Vue.use(Vuex); // 现在我们定义完了,此时就要将我们定义的内容暴露出去 export default new Vuex.Store({ modules : { user } });
由于组件中使用的是
getters
和actions
处理,所以调用代码不变 -
修改
App.vue
export default { name: 'App', mounted() { window.addEventListener('unload', this.saveState); } , methods: { saveState() { window.sessionStorage.setItem('userState', JSON.stringify(this.$store.state.user)) } } }