本文主要介绍如何通过Vue的状态管理框架Vuex来管理一些被不同组件或不同页面共同使用的数据,然后展示如何通过状态管理用户信息,并且在具体页面获取用户信息,并且根据用户信息的不同展示不同的页面内容。
文章目录
- 本系列前文传送门
- 一、场景说明
- 二、状态管理Vuex
- 安装vuex
- 状态管理 - 创建状态
- 状态管理 - 在代码各处使用创建的状态
- 状态管理 - 在代码中更新状态管理的值
- 三、用户登录数据如何流转如何变化
- 四、简单模拟用户登录过程
本系列前文传送门
- 「网页开发|前端开发|Vue」01 快速入门:快速写一个Vue的HelloWorld项目
- 「网页开发|前端开发|Vue」02 从单页面到多页面网站:使用路由实现网站多个页面的展示和跳转
- 「网页开发|前端开发|页面布局」03 学会够用的CSS,实现任意你想要的页面布局
- 「网页开发|前端开发|Vue」04 快速掌握开发网站需要的Vue基础知识
- 「网页开发|前端开发|Vue」05 Vue实战:从零到一实现一个网站导航栏
- 「网页开发|前端开发|Vue」06 公共组件与嵌套路由:让每一个页面都平等地拥有导航栏
- 「网页开发|前端开发|Vue」07 前后端分离:如何在Vue中请求外部数据
- 「网页开发|后端开发|Flask」08 python接口开发快速入门:技术选型&写一个HelloWorld接口
一、场景说明
我们在网站开发中,有些数据可能会被不同的组件或者在不同页面多次使用,对于这种重复多次使用的数据,如果每次都要重新获取或者重新生成,那么除了代码会变得冗余,还可能因为代码改动过程中的遗漏导致不同地方数据不一致而引发数据问题。
针对这种数据在多次使用的场景,我们会使用状态管理框架
来统一管理数据,使得程序更加稳定和可预测。
react
的状态管理使用redux
,而vue
的状态管理使用vuex
。接下来我们就介绍一下vuex
的核心内容,然后用一个根据用户登录状态数据展示不同页面内容
的例子来展示状态管理的具体应用场景和实现方法。
二、状态管理Vuex
如果用编程语言中我们熟悉的概念来描述状态管理的话,那状态管理就相当于一个「全局变量」,我们可以在项目的各个位置直接获取、使用、甚至更新变量的内容。
安装vuex
因为我们在示例中用的是匹配vue2
的vuex3
,所以安装时需要注意版本,如下:
npm install vuex@3
状态管理 - 创建状态
因为状态管理是管理着涉及整个项目的状态数据,所以一般我们会新建一个store
目录,在该目录下组织状态相关的代码。这里我们为了更快更简单地展示创建状态的过程,则直接在src/main.js
添加代码,如下:
状态管理 - 在代码各处使用创建的状态
创建状态管理store
,并且传入到Vue实例
中后,我们就可以在项目的各个代码中访问store
中的状态数据了。
如果我们是在src/main.js
中访问,直接使用变量名store
即可(因为我们就是在这里将状态管理实例导入为store
),比如console.log(store.state.count)
如果是在其他文件中,比如在HelloWorld.vue
中,则使用this.$store
来访问,比如console.log(this.$store.state.count)
状态管理 - 在代码中更新状态管理的值
我们可以像修改变量值一样,直接修改状态的值。这给了我们极大的自由,但是这也可能会导致我们管理的状态被以各种方式被修改,导致出现预期之外的结果。
所以会推荐开启严格模式(在创建store时传入strict: true
),然后封装修改对应状态值的方法供代码各处调用。相当于回归了程序员的本质:降低系统复杂度、降低程序不确定性。
那么vuex
的设计中,如何封装方法并在代码各处调用的呢?
那就是在创建store
时,定义mutations
和actions
两个字段,并在字段值中定义各个方法。两个字段都可以定义操作状态值的方法,主要差别是:
mutations
是同步操作,actions
是异步操作;mutations
直接操作状态值,actions
使用commit(方法名)
调用mutations
方法操作状态值
所以我们可以将创建的store
改为如下:
const store = new Vuex.Store({
strict: true,
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
asyncIncrement (context) {
context.commit('increment')
}
}
})
然后就可以在项目的各处代码中使用this.$store.commit(mutations中的方法名)
以及this.$store.dispatch(actions中的方法名)
来调用mutations
和actions
中定义的方法。
比如我们在HelloWorld.vue
的script
中增加如下方法:
methods: {
increase() {
console.log(`[ Before ] ${this.$store.state.count}`);
this.$store.commit("increment");
console.log(`[ After ] ${this.$store.state.count}`);
},
asyncIncrease() {
console.log(`[ Before ] ${this.$store.state.count}`);
this.$store.dispatch("asyncIncrement");
console.log(`[ After ] ${this.$store.state.count}`);
},
},
然后在template
的部分增加count
的展示以及两个更新count
的按钮,如下:
返回页面,我们就可以看到浏览器页面已经展示count
的值以及两个增加按钮,如下:
我们可以点按两个按钮来观察同步和异步的效果,如下:
我们可以看到我们点击异步的时候,由于我们在代码中设置了等待1秒再增加count
的值,所以输出的前后值是相同的,等待1s后再点击按钮就可以观察到值已经变化。最后我们连续快速点击3次异步增加,可以看到3次点击完成后,值仍然是4,但是等待1秒之后,值变成了7(看页面按钮上面展示的count
值)
三、用户登录数据如何流转如何变化
在明白状态管理的基本操作之后,我们就可以来考虑一个状态管理的常见场景:管理用户登录信息。
首先,我们要确认要放到状态管理中的信息是不是会在多个地方使用到。用户登录信息是用户登录之后,在网站的各个页面都应该是共用的,最起码右上角显示的用户登录状态都应该是一致的,不能首页登录后右上角已经显示了用户登录状态,切换到其他页面右上角又变成了登录/注册按钮。所以用户登录信息确实适合放到状态管理中。
然后我们考虑用户登录信息的存储结构。比如我们可以放一个名为user
的object
值在store.state
中,然后在各个页面通过访问this.$store.state.user.具体用户信息字段
访问用户信息中的各个信息。
于是我们就可以清楚用户注册/登录的一个基本流程了,如下:
- 我们在页面检查状态管理
store
中是否存在user
,需要不存在用户信息,则在页面右上角显示"登录/注册"按钮; - 当我们通过注册/登录页面进行注册和登录后,在状态管理中存入对应的用户信息(用户来自后端,所以涉及接口交互);
- 状态管理中的用户信息变化后,页面检测到
store
中的user
已经存在,自动重新渲染,在页面右上角渲染出登录的用户信息。
四、简单模拟用户登录过程
明白用户登录的基本流程之后,我们可以简单通过代码模拟一下整个过程。实际的登录过程涉及接口请求以及登录和注册页的开发,我们目前只是要模拟登录前后的页面变化,所以将流程简化如下:
- 页面检查
store
中是否有用户信息,如果没有,展示一个登录按钮
;否则展示用户信息以及一个登出
按钮; - 给
登录
按钮增加功能:点击后往store
中写入用户信息; - 给
登出
按钮增加功能:点击后删除store
中的用户信息; - 通过点击
登录
和登出
来观察用户信息变化与页面变化过程;
首先在src/main.js
中增加代码,用来创建store
,在store
中定义登录和注销登录的方法,如下:
const store = new Vuex.Store({
state: {
user: {}
},
mutations: {
mock_login() {
this.state.user = {
userId: 1111,
userName: "明仔的阳光午后",
};
sessionStorage.setItem("user", JSON.stringify(this.state.user));
},
mock_logout() {
this.state.user = undefined;
sessionStorage.removeItem("user");
},
},
})
然后在HelloWorld.vue
中script
的部分添加从store
中获取user
信息以及操作user
信息的方法,如下:
<script>
export default {
data() {
return {
user: JSON.parse(sessionStorage.getItem("user")),
};
},
methods: {
login() {
this.$store.commit("mock_login");
this.user = this.$store.state.user;
},
logout() {
this.$store.commit("mock_logout");
this.user = this.$store.state.user;
},
},
}
</script>
之后在HelloWorld.vue
中template
部分增加一个h1
用来展示当前登录状态,一个button
用来提供登录和登出的点按功能,这样我们才能直接通过点按来模拟登录过程并观察页面内容变化。如下:
<template>
<div id="app">
<div v-if="user">
<h1>Hi, {{ user.userName }}</h1>
<button @click="logout">登出</button>
</div>
<div v-else>
<h1>当前未登录</h1>
<button @click="login">登录</button>
</div>
</div>
</template>
完成上述代码改动,我们就可以回到浏览器页面,看到页面内容如下:
我们点击登录
按钮之后,页面变化如下:
我们看到,页面的标题展示了具体的用户名,同时登录
按钮变成了登出
按钮。可以验证页面实现了根据用户登录状态来渲染不同的内容。
所以通过这样一个过程,我们就可以在其他需要页面根据不同数据,比如用户登录状态,或者用户身份、用户权限等等,来渲染不同页面内容的应用场景中,按照上述的流程来轻松实现我们想要的需求。
比如可以自己试试让导航栏根据用户登录状态来展示用户信息
或者登录/注册
按钮。
写文不易,如果对你有帮助的话,来一波点赞、收藏、关注吧~👇