实现登录业务
实现步骤:
- 准备一个新的请求接口模块
AdminApi.js
。提供登录接口。 - 准备一个登录页面,
views/user/Login.vue
。访问:/user/login
看到它。 - 在登录页面的表单中,填写账号与密码,实现登录业务,获取当前登录用户的基本信息与
token
。跳转到首页。 - 在首页右上角显示当前登录用户,实现刷新页面后不消失。
Vuex
Vue
官方推荐的全局状态管理器
在脚手架项目的实现过程中,避免不了需要将一些数据存储在全局,方便在任何组件中直接获取并使用的需求。这种需求就非常契合vuex
的功能,vuex
主要用于将一些数据实现全局存储,需要的时候直接访问vuex
即可获取这些数据。
官方文档:https://vuex.vuejs.org/zh/guide/
。
Vuex
和核心js
文件: src/store/index.js
,提供了vuex
内置的5
个对象:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
// 此处用于存储全局共享的状态数据
state: {
user: null, // user用于存储当前登录用户
},
// getters用于提供一些方法,方便的获取state中数据的临时计算结果
// 类似vue中的计算属性:computed
getters: {
},
// mutations用于提供一些方法,修改state中的状态数据
mutations: {
},
actions: {
},
modules: {
}
})
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-58KSsBHM-1669080333163)(D:\code\TS_OOP\day01\note\assets\1668744290146.png)]
state
: 此处用于存储全局共享的状态数据,可以直接将数据定义在此处,全局可用:
state: {
user: {name: 'zs'}
}
在vue
组件中使用:通过this.$store
访问vuex
的仓库:
let name = this.$store.state.user.name
<div>{{$store.state.user.name}}</div>
mutations
: 用于提供一些方法,修改state
中的状态数据:
mutations:{
// 这个方法完全被vuex所管理,由vuex来调用,参数由vuex来传递
// vuex将会传过来两个参数:
// state: 当前vuex仓库的state对象
// newName: 形参,由用户指定,vuex将会把用户的参数也带过来赋值给newName
updateName(state, newUser){
state.user = newUser
}
}
mutations
中的方法定义完成后,用户可以通过以下代码来调用这个方法,从而修改state
中的数据:
// commit方法用于通知vuex:“vuex,请你执行updateName方法,顺便给你传个参数”
// this.$store.commit('mutations方法名称', 自定义参数信息)
this.$store.commit('updateName', {id:1, user:'温柔的亮', email:'xxx'})
actions
: actions
: 用于提供一些方法,异步做了一些耗时任务后,修改state
中的状态数据 , (不能直接修改state,而是需要调用mutations中的方法,来修改state)。
actions: {
// 这个方法完全被vuex所管理,由vuex来调用,参数由vuex来传递
// vuex将会传过来两个参数:
// store: 当前vuex仓库Store对象
// payload: 形参,由用户指定,vuex将会把用户的参数也带过来赋值给payload
login(store, payload){
// 执行异步任务,发送请求,得到结果后
// 将异步任务的结果交给mutations来进行后续处理
// store.commit('updateUserInfo', 用户对象)
}
},
如何调用actions
的方法呢?
// this.$store.dispatch('actions中的方法名称', 用户自定义的参数)
this.$store.dispatch('login', {username:'zs', password:'123456'})
module
:由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store
对象就有可能变得相当臃肿。
为了解决以上问题,Vuex
允许我们将 store
分割成模块(module)。每个模块拥有自己的 state
、mutation
、action
、getter
、甚至是嵌套子模块。
虽然vuex
可以实现SPA(Single Page Application)
单页面应用的状态信息的管理。但是一旦用户刷新浏览器,就会重新加载vue
的环境,当然也会初始化所有的vuex
中的数据。这是就需要实现以前存在vuex
中的数据的持久化存储(刷新不消失)。
如果希望vuex
中的数据持久保存,单用vuex
就不够了,还需要借助于sessionStorage
与localStorage
来解决问题。
window.sessionStorage 关了浏览器,会话断开,数据销毁
window.localStorage 永久存储
为什么不直接用Storage
存储数据呢?因为Storage
将数据存至磁盘,并不能实现数据更新的响应式效果(页面显示与数据变化适时同步)。vuex
中的数据是可以与ui显示实时同步的。一般情况下二者同时使用,配合在一起实现功能。
state: {
// user用于存储当前用户, 初始化赋值为storage中存储的用户
user: JSON.parse(sessionStorage.getItem('user')),
},
mutations: {
updateUserInfo(state, payload){
// 将用户传过来的登录成功的use对象存入state.user
state.user = payload
// 存入vuex后还不够,还需要存入sessionStorage
sessionStorage.setItem('user', JSON.stringify(payload))
}
}
发现一个大bug
,不登录也可以对数据进行增删改查。 实际上,应该实现如下业务场景:
- 只有登录后,才可以看到除登录之外的页面。
- 只有登录后,才可以发送其他的
http
增删改查的请求,否则不应该可以访问数据。
只有登录后,才可以看到除登录之外的页面。
实现思路:在项目的VueRouter
对象中添加前置守卫,前置守卫将会在跳转路由页面之前先执行,我们就可以在此处判断,用户访问当前地址时,vuex
里是否有当前用户,如果有可以通过,如果没有,直接拦截后,强制跳转到登陆页面。
只有登录后,才可以发送登录请求之外的http
的请求
如果想要实现该功能,则需要服务端进行请求验证,验证当前请求中是否包含登录用户的身份(服务端需要完成用户身份的鉴权),如果该用户拥有操作数据的权限,则执行相应业务;如果该用户没有处理该请求的权限,则直接打回去,返回一个错误消息:您没有操作该模块的权限。
基于Token
机制重构所有的请求
- 当发送登录请求,得到响应后,不仅可以获取到当前登录用户,还可以获取到一个服务端返回回来的
Token
加密字符串。这个字符串客户端看不懂,由服务端生成,在该Token
字符串中,包含了很多与用户相关的信息:userId
nickname
email
phone
过期时间
等信息。 - 客户端获取该
token
字符串后,需要将token
存起来,当做是当前用户的身份标识符,以后发送任何的请求时,都要携带该token
字符串一起发送请求。 - 这样服务端就可以接收该请求,解析出
token
后进行解密,解密出用户信息,从而了解该请求是哪一个用户发出的,完成用户鉴权后实现后续业务。