一、登录注册静态组件
assets文件夹放置全部组件共用静态资源,打包后在js中
二、注册业务
const {phone}= this相当于 const phone = this.phone
//获取验证码按钮的回调
async getCode() {
const { phone } = this;
//先不处理表单验证业务
if (phone) {
try {
//获取验证码成功
await this.$store.dispatch("getCode", phone);
//修改VC身上的code属性,让验证码自动展示
this.code = this.$store.state.user.code;
} catch (error) {}
}
},
//获取验证码
async getCode({ commit, state, dispatch }, phone) {
let result = await reqGetCode(phone);
if (result.code == 200) {
commit('GETCODE', result.data);
return 'ok';
} else {
return Promise.reject();
}
}
GETCODE(state, code) {
state.code = code;
},
//注册按钮的回调
async register() {
//解构出参数
const { phone, code, password, password1 } = this;
//目前不做表单验证
if (phone && code && password == password1) {
//通知vuex发请求,进行用户的注册
try {
//注册成功
await this.$store.dispatch("registerUser", { phone, code, password });
//让用户跳转到登录页面进行登录
this.$router.push('/login');
} catch (error) {
//注册失败
alert(error.message);
}
}
},
//注册用户的地方
async registerUser({ commit, state, dispatch }, obj) {
//注册接口没有返回data,不需要提交mutation
let result = await reqRegister(obj);
if (result.code == 200) {
//注册成功
return 'ok';
} else {
//注册失败
return Promise.reject(new Error(result.message));
}
}
三、登录
登陆成功的时候,后台为了区分你这个用户是谁,服务器下发token,前台持久化存储token,前台带着token找服务器要用户信息进行展示
当用户注册完成,用户登录向服务器发送请求,登陆成功获取到token,存在仓库中(非持久化),路由跳转到home首页
在首页组件挂载完毕后,派发action获取用户信息,展示在header组件内
但是,一刷新,home首页获取不到用户信息
使用全局路由守卫解决
持久化token
阻止表单的默认行为,点击自动跳转页面
<button class="btn" @click.prevent="login">
登 录
</button>```
```javascript
//登录按钮
async login() {
//整理参数
const { phone, password } = this;
//在发登录请求
try {
//登录成功
await this.$store.dispatch("userLogin", { phone, password });
//若地址栏中有redirect参数,则跳往该地址
let goPath = this.$route.query.redirect||'/home';
//跳转到首页
this.$router.push(goPath);
} catch (error) {
alert(error.message);
}
},
vuex的数据存储是非持久化的,所以需要将token存入本地存储
//用户登录的地方:非常非常重要
async userLogin({ commit, state, dispatch }, data) {
//接口说明:后台老师目前登录接口返回数据不正确的,以后工作的时候登录接口成功,返回格式100%和相面例子一样的!!!
/*
举例子
{
code:200,
data:{
token:'1e4vdadhajkhdakj6sahdajk'
},
message:'登录成功'
}
*/
let result = await reqUserLogin(data);
//登录成功
if (result.code == 200) {
commit('SET_TOKEN', result.data.token);
//以后开发的时候:经常的登录的成功获取token【持久化存储】
localStorage.setItem('TOKEN', result.data.token);
return 'ok';
} else {
//登录失败
return Promise.reject(new Error(result.message));
}
}
1.用户携带token获取用户信息
请求拦截器中设置请求头携带token
//获取用户信息
async getUserInfo({ commit, state, dispatch }) {
let result = await reqUserInfo();
if (result.code == 200) {
commit('SET_USERINFO', result.data.nickName);
return 'ok';
} else {
return Promise.reject();
}
},
SET_USERINFO(state, nickName) {
state.nickName = nickName;
},
<!-- 没有登录:显示登录与注册 -->
<p v-if="!$store.state.user.nickName">
<span>请</span>
<!-- <a href="###">登录</a> -->
<!--
声明式导航,当然你也可以使用编程式导航,因为不管是那个导航,都可以实现路由跳转,
但是最后为什么选择声明式导航,没有任何业务、逻辑
-->
<router-link to="/login">登录</router-link>
<router-link class="register" to="/register">注册</router-link>
</p>
<!-- 如果登录显示的是用户名字与退出登录 -->
<p v-else>
<a>{{$store.state.user.nickName}}</a>
<a class="register" @click="logout">退出登录</a>
</p>
3.解决登录后的用户信息展示
退出登录
1.通知服务器退出登录
2.清除项目中的数据(userInfo token)
//退出登录的按钮的回调
logout(){
//派遣action退出登录
this.$store.dispatch('logout');
}
user.js
服务器中清除
//退出登录的业务
async logout({ commit, state, dispatch }) {
//发请求通知服务器销毁当前token【学生证】
//清除服务器中的登录
let result = await reqUserLogout();
if (result.code == 200) {
commit('CLEAR');
return 'ok';
} else {
return Promise.reject(new Error(result.message));
}
}
清除本地存储
CLEAR(state) {
//清除仓库相关用户信息
state.token = '';
state.nickName = '';
//本地存储令牌清空
localStorage.removeItem('TOKEN');
}
//全局守卫:只要项目中有任何路由变化,全局守卫都会进行拦截【符合条件走你,不符合条件不能访问】
//全局守卫:全局前置守卫【访问之前进行触发】
//全局前置守卫
router.beforeEach(async (to, from, next) => {
//to:去的那个路由的信息
//from:从那个路由而来的信息
//next:放行函数!!!!!!
//第一种:next(),放行函数,放行到指定的路由!!!
//第二种:next(path),守卫指定放行到那个路由去?
//用户是否登录:取决于仓库里面是否有token!!!
//每一次路由跳转之前需要用有用户信息在跳转,没有发请求获取用户信息在跳转!!!!
//token
let hasToken = store.state.user.token;
//用户信息
let hasNickName = store.state.user.nickName;
//用户登录
if (hasToken) {
//用户登录了,不能去login
if (to.path == "/login") {
next('/home');
} else {
//用户登陆了,而且还有用户信息【去的并非是login】
if (hasNickName) {
next();
} else {
//用户登陆了,但是没有用户信息
try {
//发请求获取用户信息以后在放行
await store.dispatch('getUserInfo');
next();
} catch (error) {
//用户没有信息,还携带token发请求获取用户信息【失败】
//token【学生证失效了】
//token失效:本地清空数据、服务器的token通知服务器清除
await store.dispatch('logout');
//回到登录页,重新获取一个新的学生证
next('/login');
}
}
}
} else {
//用户未登录||目前的判断都是放行.将来这里会'回手掏'增加一些判断
//用户未登录:不能进入/trade、/pay、/paysuccess、/center、/center/myorder /center/teamorder
let toPath = to.path;
if (toPath.indexOf('trade') != -1 || toPath.indexOf('pay') != -1 || toPath.indexOf('center') != -1) {
// 先跳往login页进行登陆,将未登录前的路径存在路由中,发送至登录页面
next('/login?redirect='+toPath);
} else {
next();
}
}
});
1.全局前置路由守卫
关于未登录的地址拦截\跳转
例如,未登录时不能去往个人中心,如果点击去往个人中心,全局前置路由守卫判断用户未登录,携带目标地址跳往login页面,登录成功后才能自动跳往目标页面
//用户未登录||目前的判断都是放行.将来这里会'回手掏'增加一些判断
//用户未登录:不能进入/trade、/pay、/paysuccess、/center、/center/myorder /center/teamorder
let toPath = to.path;
if (toPath.indexOf('trade') != -1 || toPath.indexOf('pay') != -1 || toPath.indexOf('center') != -1) {
// 先跳往login页进行登陆,将未登录前的路径存在路由中
next('/login?redirect='+toPath);
} else {
next();
}
//在发登录请求
try {
//登录成功
await this.$store.dispatch("userLogin", { phone, password });
// 若地址栏中有redirect参数,则跳往该地址
let goPath = this.$route.query.redirect||'/home';
//跳转到首页
this.$router.push(goPath);
} catch (error) {
alert(error.message);
}
2.独享路由守卫
在路由配置处配置
3.组件内路由守卫
beforeRouterEnter 在渲染该组件的对应路由被confirm之前调用
beforeRouterUpdate 路由发生改变 动态参数
beforeRouterLeave