概述
Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
安装
- 在项目根目录执行如下命令来安装 Vuex
npm install vuex --save --registry=https://registry.npm.taobao.org
- 修改
main.js
文件,导入 Vuex,关键代码如下:
import Vuex from 'vuex'
Vue.use(Vuex);
状态管理
我们利用路由钩子 beforeEach
来判断用户是否登录,期间会用到 sessionStorage
存储功能
修改 Login.vue
在表单验证成功方法内增加如下代码:
// 设置用户登录成功 sessionStorage.setItem('isLogin', 'true');
修改 main.js
利用路由钩子 beforeEach
方法判断用户是否成功登录,关键代码如下:
1 // 在跳转前执行 2 router.beforeEach((to, form, next) => { 3 // 获取用户登录状态 4 let isLogin = sessionStorage.getItem('isLogin'); 5 // 注销 6 if (to.path == '/logout') { 7 // 清空 8 sessionStorage.clear(); 9 // 跳转到登录 10 next({path: '/login'}); 11 } 12 // 如果请求的是登录页 13 else if (to.path == '/login') { 14 if (isLogin != null) { 15 // 跳转到首页 16 next({path: '/main'}); 17 } 18 } 19 // 如果为非登录状态 20 else if (isLogin == null) { 21 // 跳转到登录页 22 next({path: '/login'}); 23 } 24 // 下一个路由 25 next(); 26 });
配置 Vuex
- 创建 Vuex 配置文件
在 src
目录下创建一个名为 store
的目录并新建一个名为 index.js
文件用来配置 Vuex,代码如下:
1 import Vue from 'vue' 2 import Vuex from 'vuex' 3 Vue.use(Vuex); 4 // 全局 state 对象,用于保存所有组件的公共数据 5 const state = { 6 // 定义一个 user 对象 7 // 在组件中是通过 this.$store.state.user 来获取 8 user: { 9 username: '' 10 } 11 }; 12 // 实时监听 state 值的最新状态,注意这里的 getters 可以理解为计算属性 13 const getters = { 14 // 在组件中是通过 this.$store.getters.getUser 来获取 15 getUser(state) { 16 return state.user; 17 } 18 }; 19 // 定义改变 state 初始值的方法,这里是唯一可以改变 state 的地方,缺点是只能同步执行 20 const mutations = { 21 // 在组件中是通过 this.$store.commit('updateUser', user); 方法来调用 mutations 22 updateUser(state, user) { 23 state.user = user; 24 } 25 }; 26 // 定义触发 mutations 里函数的方法,可以异步执行 mutations 里的函数 27 const actions = { 28 // 在组件中是通过 this.$store.dispatch('asyncUpdateUser', user); 来调用 actions 29 asyncUpdateUser(context, user) { 30 context.commit('updateUser', user); 31 } 32 }; 33 export default new Vuex.Store({ 34 state, 35 getters, 36 mutations, 37 actions 38 });
- 修改
main.js
增加刚才配置的store/index.js
,关键代码如下:
1 import Vue from 'vue' 2 import Vuex from 'vuex' 3 import store from './store' 4 Vue.use(Vuex); 5 new Vue({ 6 el: '#app', 7 store 8 });
浏览器刷新 Vuex 数据消失
问题描述
Vuex 的状态存储是响应式的,当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。但是有一个问题就是:vuex 的存储的数据只是在页面的中,相当于我们定义的全局变量,刷新之后,里边的数据就会恢复到初始化状态。但是这个情况有时候并不是我们所希望的。
解决方案
监听页面是否刷新,如果页面刷新了,将 state 对象存入到 sessionStorage 中。页面打开之后,判断 sessionStorage 中是否存在 state 对象,如果存在,则说明页面是被刷新过的,将 sessionStorage 中存的数据取出来给 vuex 中的 state 赋值。如果不存在,说明是第一次打开,则取 vuex 中定义的 state 初始值。
修改代码
在 App.vue
中增加监听刷新事件
1 export default { 2 name: 'App', 3 mounted() { 4 window.addEventListener('unload', this.saveState); 5 }, 6 methods: { 7 saveState() { 8 sessionStorage.setItem('state', JSON.stringify(this.$store.state)); 9 } 10 } 11 }
修改 store/index.js
中的 state
const state = sessionStorage.getItem('state') ? JSON.parse(sessionStorage.getItem('state')) : { user: { username: '' } };
模块化
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
创建 user 模块
在 store
目录下创建一个名为 modules
的目录并创建一个名为 user.js
的文件,代码如下:
1 const user = { 2 // 因为模块化了,所以解决刷新问题的代码需要改造一下 3 state: sessionStorage.getItem('userState') ? JSON.parse(sessionStorage.getItem('userState')) : { 4 user: { 5 username: '' 6 } 7 }, 8 getters: { 9 getUser(state) { 10 return state.user; 11 } 12 }, 13 mutations: { 14 updateUser(state, user) { 15 state.user = user; 16 } 17 }, 18 actions: { 19 asyncUpdateUser(context, user) { 20 context.commit('updateUser', user); 21 } 22 } 23 }; 24 export default user;
修改 store/index.js
1 import Vue from 'vue' 2 import Vuex from 'vuex' 3 import user from './modules/user' 4 Vue.use(Vuex); 5 export default new Vuex.Store({ 6 modules: { 7 // this.$store.state.user 8 user 9 } 10 });
备注: 由于组件中使用的是 getters
和 actions
处理,所以调用代码不变
修改 App.vue
1 export default { 2 name: 'App', 3 mounted() { 4 window.addEventListener('unload', this.saveState); 5 }, 6 methods: { 7 saveState() { 8 // 模块化后,调用 state 的代码修改为 this.$store.state.user 9 sessionStorage.setItem('userState', JSON.stringify(this.$store.state.user)); 10 } 11 } 12 }