一、登录模块
代码步骤:
1.表单验证
在Login->index.vue中 进行表单验证---修改data数据中username(根据接口文档命名),同时在src->utils->validate.js中修改手机号正则。
2.发送请求:
在rc->utils->request.js下,导入axios,设置基地址,导出axios实例,在src->api下的user.js页面中,发送请求并封装成函数。最后在src->views->login下的index.vue中 导入login函数,并在methods中调用函数,这里注意:可以进行二次封装,定义一个新函数doLogin,用于接收axios返回值,在新函数doLogin中调用
3.存储token:
在vuex中state中定义token变量(可读),在mutations中声明函数,注意:mutations函数可以修改state中的数据。然后在doLogin函数中通过this.$store.commit('user/getToken',res.data)传值,因为开启了命名空间,所以需要添加模块名/user
4.环境变量
在.env.development文件中,通过port= xxxx 可以修改端口号,也可以自定义设置接口,通过变量名 = 地址方式 VUE_APP_BASE_API = '/dev-api' 变量命名建议以VUE_APP为主,在src->utils->request.js文件中 ,通过process.env.VUE_APP_BASE_API 设置基地址
5.跨域
跨域出现是因为,协议、域名、端口号不一致时,而后端没有进行处理时,会出现的问题,解决方式一般为添加一个代理服务器,在vue.config.js文件中 的devServer下面添加代理服务器
6.添加请求拦截器
在src->utils->request.js文件中,通过axios官网C一份请求拦截器的代码,在发送请求之前,添加请求头Token,根据接口文档中的Authorization的格式来存储token,因为没有开启持久化,所以刷新token还是会没有,这个我们后面会做
7.添加响应拦截器
通过响应而来的数据的message的值进行判断,如果判断不通过,则抛出一个错误,而这个错误,可以通过doLogin函数的catch中的err来捕获,反之则返回一个去壳的对象,包含(token,success)等参数
8.持久化token
在src->utils->auth.js文件中,导入js-cookie,自定义token名,定义存储token、取出token、移除token三种函数,在mutations函数中导入并调用。
二、主页模块
代码步骤
1、模块化处理
在login下面的index.vue文件中,将获取用户档案信息发送请求提取在store->modules->user.js文件中的actions中,声明一个函数userLogin,将index.vue文件中的参数通过this.$store.dipatch(模块名/函数,参数)传递过来,通过userLogin函数里两个参数,context.commit进行调用mutations进行调用,在state里进行存储token,obj用于接收表单数据。
2、路由导航守卫-两个页面跳转
在src->permission.js文件中,声明一个路由守卫,beforeEach,将token拿过来进行判断,有token不让去登录页,其他页面放行,反之相反,考虑后面不止一个页面,所以定义白名单数组,用于路径地址判断,在条件判断中,通过数组.includes()方法进行筛选。
import router from './router'
import store from './store'
import NProgress from 'nprogress' // progress bar // 下载导入进度条包
import 'nprogress/nprogress.css' // progress bar style
NProgress.configure({ showSpinner: false }) // NProgress Configuration // 取消转圈圈
const whiteList = ['/login','/404'] // 存储路径的白名单数据
router.beforeEach( async (to,from,next)=>{
// console.log(to.path);//去哪里
// console.log(from.path)// 来自哪里
// next()// 放行
// console.log(store);
NProgress.start() // 开启进度条
const token = store.state.user.token
if(token){
// 有token
if(to.path === '/login'){
next('/')
NProgress.done() // 结束进度条
} else {
// 跳转首页
// 这里actions函数是异步操作,所以需要async,await修饰
await store.dispatch('user/getuserProfile')
next()
}
} else {
// 没有token
if(whiteList.includes(to.path)){
// 数组.includes方法进行筛选有没有,有则true,反之false
next()
} else {
next('/login')
NProgress.done() // 结束进度条
}
}
})
// 路由跳转之后
router.afterEach((to,from)=>{
NProgress.done() // 结束进度条
})
3、修改样式---见资料
4、显示用户名---分析
在api->user.js文件中封装一个获取用户信息的请求(需要传id),在store->user.js文件中的 mutations中,声明一个用于存用户信息的函数,通过actions进行调用,将用户档案信息中的id传给axios请求,获得用户信息,在通过对象...方式,保存完整的用户信息资料,最后在src->components->Navbar.vue中显示用户名和图片(插值表达式和: $store.state.user.userInfo.XXXX)
mutations: {
// 1.定义函数,通过mutations修改state里的值
setToken(state,newToken) {
state.token = newToken
// 2. token持久化处理
setToken(newToken)
},
// 存用户信息
setUserInfo(state,newUserInfo){
state.userInfo = newUserInfo
}
},
actions:{
async getuserProfile(context){
const {data:res} = await userProfile()
// console.log(res)
// 通过context.commit方法调用,修改mutations函数里的token值
// console.log(res);
// 2.获取用户信息函数---需要传入参数
const {data:resInfo} = await userInfo(res.userId)
// console.log(resInfo.data);
const obj = {...res,...resInfo}
// 将用户信息传过去
context.commit('setUserInfo',obj)
},
}
5、实现用户退出
在store/modules/user.js中,补充一个action
// 3.定义函数,用于清空token,用户信息
logout(context) {
context.commit('setUserInfo',{})
context.commit('setToken','')
}
在Navbar.vue文件中,通过定义函数logout(){{}.then()}方法,进行退出,退出时要清空用户信息和token,实现页面跳转。可以使用thiis.router.push()进行路径跳转
logout() {
this.$confirm('你确定要离开吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then( async ()=>{
// 1.清除token、清空用户信息
await this.$store.dispatch('user/logout')
// 2.跳转到首页(登录页)------跳转到上次退出时的页面,通过地址拼接
// 是js的内置API,用来对url进行编码,可以携带地址后面的所以参数,并转译
this.$router.push('/login?return_url=' + encodeURIComponent(this.$route.fullPath))
})
}
6、退出再进入能回到原来的页面
1.登录成功之后,进入指定的目标页面(不要每次都进入主页)
2.用户退出,跳入登录页时,携带目标页面地址告诉登录页
在scr->login->index.vue中,在点击登录的函数中doLogin(){},定义一个路径
async doLogin() {
try {
// 在组件中调用带命名空间的action
// dispatch是异步的,需要加async await
await this.$store.dispatch('user/userLogin', this.loginForm)
// 登录成功,路由跳转
+ this.$router.push(this.$route.query.return_url || '/')
} catch (err) {
alert('用户登录,失败')
console.log('用户登录,失败', err)
}
},
在点击退出时,在Navbar.vue文件中,在退出登录时,添加
//跳转到首页(登录页)------跳转到上次退出时的页面,通过地址拼接
//是js的内置API,用来对url进行编码,可以携带地址后面的所以参数,并转译
this.$router.push('/login?return_url=' + encodeURIComponent(this.$route.fullPath))
7.token失效处理
在src->request.js中,通过响应拦截器的error,进行状态码判断,可以通过console.dir来获取错误对象,从而清空用户信息,跳转页面。
// 添加响应拦截器
service.interceptors.response.use(function (response) {
// 对响应数据做点什么
// console.log(response);
// 如果响应过来的数据等于false,则抛出promise错误对象信息
if(response.data.success === false) {
return Promise.reject(response.data.message);
}
// 反之返回成功数据(通过response.data处理脱壳--在调用时,可以简写一些)
return response.data;
}, function (error) {
// console.dir(error)
if(error.response.data.code === 10002){
// 1.清除token,
store.dispatch('user/logout')
// 2.跳转页面
router.push('/login?return_url=' + encodeURIComponent(this.$route.fullPath))
}
// 对响应错误做点什么
return Promise.reject(error);
});
\