目录
- 登录与注册(重要)
- 静态组件
- 注册页面
- 获取验证码
- 完成注册
- 登录页面
- 登录跳转
- token获取用户信息
- 退出登录
- 导航守卫
登录与注册(重要)
静态组件
- assets文件夹:放置全部组件共用静态资源
- 在样式中也可以使用@符号【src别名】,切记要在前面加一个~
注册页面
获取验证码
1、写接口
//获取验证码 地址:/api/user/passport/sendCode/{phone} 请求方法:GET 参数:需要
export const reqGetCode = (phone)=> requests({url:`/user/passport/sendCode/${phone}`,method:'GET'})
2、vuex三连环
import { reqGetCode } from "@/api"
//登录与注册的模块
const state = {
code:''
}
const mutations = {
GETCODE(state,code){
state.code = code
}
}
const actions = {
//获取验证码
async getCode({commit},phone){
let result = await reqGetCode(phone)
if(result.code == 200){
commit('GETCODE',result.data)
return 'ok'
}else{
return Promise.reject(new Error('faile'))
}
}
}
const getters = {}
export default {
state,
mutations,
actions,
getters
}
获取验证码的这个接口,把验证码返回,但是正常情况后台把验证码发到用户手机上
3、点击事件
async getCode(){
try {
const{phone} = this
phone && (await this.$store.dispatch('getCode',phone))
//验证码直接填写到框内
this.code = this.$store.state.user.code
} catch (error) {
alert(error.message)
}
},
完成注册
1、接口
//注册 地址:/api/user/passport/register 请求方式:POST 参数:phone code password
export const reqUserRegister = (data)=> requests({url:'/user/passport/register',data,method:'POST'})
2、actions
//用户注册,未返回数据
async userRegister({ commit }, user) {
let result = await reqUserRegister(user)
if (result.code) {
return 'ok'
} else {
return Promise.reject(new Error('faile'))
}
}
3、点击事件
//用户注册
async userRegister() {
try {
const { phone, code, password, password1 } = this;
phone &&
code &&
password == password1 &&
(await this.$store.dispatch("userRegister", {
phone,
code,
password,
}));
this.$router.push('/login')
} catch (error) {
alert(error.message);
}
},
登录页面
登录跳转
1、收集表单数据
2、接口
//登录 地址:/api/user/passport/login 请求方式:POST 参数:phone password
export const reqUserLogin = (data)=> requests({url:'/user/passport/login',data,method:'POST'})
2、vuex
//登录业务[token]
async userLogin({ commit }, data) {
let result = await reqUserLogin(data)
//服务器下发的token是用户的唯一标识
if (result.code == 200) {
commit('USERLOGIN', result.data.token)
return 'ok'
} else {
return Promise.reject(new Error('faile'))
}
}
登录成功时,后台为了区分这个用户是谁,服务器会下发token【令牌:唯一标识】,一般会持久化存储token,再带着token找服务器要用的信息进行展示。
注意:vuex仓库存储数据不是持久化
3、点击事件
<button class="btn" @click.prevent="userLogin">登 录</button>
取消表单的默认行为
//用户登录
async userLogin() {
try {
const { phone, password } = this;
phone &&
password &&
(await this.$store.dispatch("userLogin", { phone, password }));
this.$router.push("/home");
} catch (error) {
alert(error.message);
}
},
token获取用户信息
1、接口
//携带token获取用户的信息 地址:/api/user/passport/auth/getUserInfo 请求方式:GET
export const reqUserInfo = ()=> requests({url:'/user/passport/auth/getUserInfo',method:'GET'})
2、在请求拦截器中在请求头携带token
//判断需要携带token
if(store.state.user.token){
config.headers.token = store.state.user.token
}
3、vuex
//获取用户信息
async getUserInfo({commit}){
let result = await reqUserInfo()
if(result.code == 200){
commit('GETUSERINFO',result.data)
return 'ok'
}else{
return Promise.reject(new Error('faile'))
}
},
4、在TheHome组件挂载完毕之后派发action
//获取用户信息在首页展示
this.$store.dispatch('getUserInfo',this.token)
5、在TheHeader组件展示数据
computed:{
userName(){
return this.$store.state.user.userInfo.name
}
}
<p v-if="!userName">
<span>请</span>
<!-- 声名式导航:务必要有to属性 -->
<router-link to="/login">登录</router-link>
<router-link to="/register" class="register">免费注册</router-link>
</p>
<p v-else>
<a>{{userName}}</a>
<a class="register">退出登录</a>
</p>
6、当获取到token时持久化存储token
export const setToken = (token)=> {
localStorage.setItem('TOKEN',token)
}
export const getToken = ()=> {
return localStorage.getItem('TOKEN')
}
获得之后本地存储
setToken(result.data.token)
state中获得
token:getToken(),
逻辑:
当未发起请求时,state中的token无法在本地中找到,即为null。当第一次发起请求即登录成功之后,token就已经本地存储了,当再次刷新时state中的token可以获得本地存储的token,所以再次刷新仍有token。
退出登录
1、接口
//退出登录 地址:/api/user/passport/logout 请求方式:GET
export const reqLogout = ()=> requests({url:'/user/passport/logout',method:'GET'})
2、actions
//退出登录
async userLogout({commit}){
let result = await reqLogout()
if(result.code == 200){
//action中不能操作state
commit('CLEAR')
return'ok'
}else{
return Promise.reject(new Error('faile'))
}
}
3、mutations
export const removeToken = ()=> {
localStorage.removeItem('TOKEN')
}
CLEAR(state){
state.token = ''
state.userInfo = {}
removeToken()
}
4、点击事件
//退出登录
async logout(){
//1、发请求
//2、清除项目当中的数据【userInfo/token】
try {
await this.$store.dispatch('userLogout')
//回到首页
this.$router.push('/home')
} catch (error) {
alert(error.message)
}
}
导航守卫
全局守卫:项目中,只要发生路由的变化,守卫就能监听到
//全局守卫:前置守卫(在路由跳转之间进行判断)
router.beforeEach(async(to,from,next)=>{
//to:跳转到哪一个组件
//from:从哪个路由来
//next:放行函数 next() next('/login')放行到指定路由 next(false)
let token = store.state.user.token
let name = store.state.user.name
if(token){
if(to.path == '/login'){
next('/')
}else{
//登录了,去的不是login
if(name){
next()
}else{
//没有用户信息,派发action
try {
//获取成功
await store.dispatch('getUserInfo')
next()
} catch (error) {
//token失效了
await store.dispatch('userLogout')
next('/login')
}
}
}
}else{
next()
}
})
export default router
TheHome组件派发的获取用户信息action删掉