1、进入首页之前在登录页面 login.vue 先将表单数据放到一个函数中,方便打包发请求,然后进行表单校验
// element-ui 表单校验
{ required: true, message: '不能为空', trigger: 'blur' },
{ pattern: /^(?:(?:\+|00)86)?1\d{10}$/, message: '手机号不合法', trigger: ['blur', 'change'] }
==================================================
// 打包的函数
loginForm: {
mobile: '',
password: '',
isAgree: false
}
========================================
// 兜底校验
this.$refs.form.validate((valid) => {
valid && this.doLogin()
})
进入到 user.js 公共仓库,在公共仓库中, actions 内发送异步请求,得到数据(包含 token)后由 mutationsn 将 token 赋值给 state
在这里还将token 存储到了本地
token 也可以称为令牌或者钥匙,有了 token 才能在网页的宫殿中通行
//
const state = {
token: getToken() || ''
}
const mutations = {
// 修改 token
alterToken(state, newToken) {
state.token = newToken
//存储到本地
setToken(state.token)
},
}
const actions = {
// 登录
async login(context, payload) {
const res = await login(payload)
const token = res.data
context.commit('alterToken', token)
console.log(res.data)
}
}
本地存储封装在 utils/auth.js ,模块化开发复用性更高、可以更好的代码组织和管理,开发效率也会更高
token 的名字尽量长一点,以免被覆盖
// token 的操作
import Cookies from 'js-cookie'
// token 名
const TokenKey = '230516-vue-lbh-rz-token'
// 存储
export function getToken() {
return Cookies.get(TokenKey)
}
// 获取
export function setToken(token) {
return Cookies.set(TokenKey, token)
}
// 删除
export function removeToken() {
return Cookies.remove(TokenKey)
}
发请求的流程繁琐,且复用性极差,可以单独封装一个 api 组件,在使用时可以直接调用 api/user.js 文件
// 登录请求
export const login = data => request.post('/sys/login', data)
在发送请求时的优化方案,配置基地址,同时处理请求超时的问题 在 utils/request.js 文件中
超时的处理尽量不要太长,否则用户体验就不太好了,单位是毫秒(ms),我现在设置的就是 5 秒(s)
// 请求基地址
const request = axios.create({
baseURL: '/api',
timeout: 5000
})
发送请求给服务器后,服务器会响应给你数据,在这中间的流程中,也有一些要问题需要处理,在这里使用 axios 来完成请求拦截器和响应拦截器
请求拦截器中,在发送请求之前给每一个请求添加 token ,具体格式根据接口文档来写,if 判断一下有 token 才加,这个是必要的
响应拦截器中,处理获取到的表单数据是否符合你的预期,如果符合就返回数据,不符合则在此处单独处理,在响应拦截器成功和错误两个函数中都是类似操作
例如:失败提示给用户
千万不要忘记导出
// 添加请求拦截器
request.interceptors.request.use(function(config) {
// 在发送请求之前做些什么
// 获取token
const token = store.state.user.token
// 在每个请求中加入 token
if (token) {
console.log(token)
config.headers.Authorization = `Bearer ${token}`
}
return config
}, function(error) {
// 对请求错误做些什么
return Promise.reject(error)
})
// 响应拦截器
request.interceptors.response.use((response) => {
// 响应成功
// 判断操作是否正确
if (response.data.success) {
return response.data
} else {
// 错误处理
// 提示用户
Message.error(response.data.message)
// 设置返回值
return Promise.reject(response.data.message)
}
// return response
}, (error) => {
// 响应失败
// 处理token 失效
if (error.response.status === 401) {
// 提示给用户
Message.error('请登录')
// 清空本地 token
store.dispatch('user/login')
// 强制跳转
router.push('/login')
}
return Promise.reject(error)
})
// 导出
export default request
发送请求成功且无误的到达服务器之后,服务器响应数据,将以上流程倒叙执行一遍,在最后是返回给 公共空间的 actions 处理,处理后,就可以将数据在浏览器内使用或渲染给即将要跳转的首页中
2、当点击登录时,需要提交在 login.vue 中校验过的表单,怎么提交? 通过 dispatch 提交给公共仓库
// 异步
await this.$store.dispatch('user/login', this.loginForm)
3、成功后跳转到首页
跳转到首页,就像刚刚说的,进入宫殿需要令牌,那么怎么验证你有没有令牌,或者说由谁来验证? 在宫殿中也会有一些开放区域,供游客浏览,开放区域则不需要令牌,但是怎么识别哪里是开放区域,哪里是只有令牌才能进入的区域呢? 做这些事情的就是导航守卫(路由的前置导航守卫),在这里处理 token 为空,和白名单的放行
在路由守卫中需要判断请求有没有携带 token ,如果携带则放行,没有携带则强制跳转到登录页面,白名单区域则可以随意浏览
在这里额外添加了进度条样式,提高用户体验
注意在放行即进入主页之前,发请求了获取用户信息详情,方便后续操作
// 进度条
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
// 白名单
const whiteList = ['/login', '/404']
// 路由导航守卫
router.beforeEach(async(to, from, next) => {
// 开启进度条
NProgress.start()
// 获取 token
const token = store.state.user.token
console.log('beforeEach', token)
// 判断
if (token) {
// 单独处理登录跳转
if (to.path === '/login') {
next('/')
// 解决进度条卡顿问题,手动关闭
NProgress.done()
} else {
// 在进入主页之前。发请求获取用户信息
// store.dispatch('user/getProfile')
if (store.getters.userId) { await store.dispatch('user/getProfile') }
next()
}
next()
} else {
// 判断去哪里
if (whiteList.includes(to.path)) {
next()
} else {
Message.error('未登录')
// 强制跳转
next('/login')
// 解决进度条卡顿问题,手动关闭
NProgress.done()
}
}
})
// 结束进度条
router.afterEach(() => {
// finish progress bar
NProgress.done()
})