一、说明
使用element组件库进行页面布局,通过路由守卫验证登录状态
主要技术栈:
- vuex库
- vue-router路由
- element组件库
二、过程
页面展示:
通过element进行页面布局
代码展示:
login.vue
<template>
<div class="login-section">
<!-- :rules="rules" -->
<el-form
label-position="top"
label-width="100px" class="demo-ruleForm"
:rules='rules'
:model='rulesForm'
status-icon
ref='rulesForm'
>
<el-form-item label="用户名" prop="name">
<el-input type="text" v-model="rulesForm.name"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="rulesForm.password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('rulesForm')">提交</el-button>
<el-button>重置</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import {login} from '@/service/api';
export default {
data() {
return {
rules:{
name:[
{ required: true, message: '名字都不写', trigger: 'blur' },
{ min: 1,max:5, message: '长度在3到5位', trigger: ['blur', 'change'] }
],
password:[
{ required: true, message: '输入密码', trigger: 'blur' },
{ min: 3,max:5, message: '长度在3到5位', trigger: ['blur', 'change'] }
]
},
rulesForm:{
name:'',
password:''
}
};
},
methods: {
submitForm(fromName){
this.$refs[fromName].validate((valid)=>{
console.log(valid);
if(valid){
// 如果校验通过,在这里向后端发送用户名和密码
login({name:this.rulesForm.name,
password:this.rulesForm.password}).then((result)=>{
console.log(result);
if(result.code===0){
localStorage.setItem('token',result.data.token)
window.location.href='/'
}
if(result.code===1){
this.$message.error(result.mes);
}
})
}else{
console.log('error submit!!');
return false
}
})
}
}
}
</script>
<style lang="stylus">
.login-section
padding 0px 20px
</style>
先进行表单校验,校验通过向后端发送用户名和密码。
判断如果result.code===0表示输入成功,跳转到首页,如果result.code===1弹出用户或密码输入错误,请重新输入
配置路由
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
import { userInfo } from '@/service/api'
import Home from '@/views/home/Home.vue'
import Detail from '@/views/detail/detail.vue'
import Store from '@/store'
const router = new Router({
mode:"history",
routes:[{
path:'/',
name:"Home",
component:Home
},{
path:'/detail',
name:"detail",
title:'详情',
component:Detail
},{
path:'/space',
name:"space",
title:'作者',
component:()=>import ('@/views/user-space/space.vue')
},{
path:'/login',
name:"login",
title:'登录页',
component:()=>import ('@/views/user-login/login.vue'),
meta:{
login:true
}
},{
path:'/register',
name:"register",
title:'注册页',
component:()=>import ('@/views/user-login/register.vue'),
meta:{
login:true
}
},{
path:'/index',
name:"index",
title:'跳转',
component:()=>import ('@/views/user-login/index.vue'),
meta:{
login:true
}
}]
});
// 路由守卫
router.beforeEach(async (to,from,next)=>{
// to :即将进入的路由信息
// from :即将离开的路由信息
// next() :是否通过
// 参数:无 通过
// false 不通过
// 具体地址 跳转到指定的地址
// 验证登录
// 有些路由是需要登录的。判断登录状态;
// 1.没有登录,跳转到登录页
// 2.登录,直接进入
// 有些路由不需要登录,直接进入
// ps:是否需要等录--meta
const token=localStorage.getItem('token')
const islogin=!!token
// 进入路由的时候,需要向后端发送token,验证是否合法
const data = await userInfo();
console.log(Store);
Store.commit('chnageUserInfo',data.data)
if(to.matched.some(item=>item.meta.login)){
console.log('需要登录');
if(islogin){ //已经登录,直接通过
if(data.error===400){//后端告诉你,登录不成功
next({name:'index'})
localStorage.removeItem('token')
return
}
if(to.name==='index'){
next({name:'home'})
}else{
next()
}
next()
return
}
if(!islogin && to.name==='index'){//未登录,但是要去登录页
next()
}
if(!islogin && to.name!=='index'){//未登录,去的不是登录页
next({name:'index'})
}
}else{
next()
}
})
export default router;
通过路由守卫进行验证登录,在需要进行登录的路由里面添加一个meta对象。需要登录的判断是否已经登录,在跳转到不同的页面
vuex库
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state:{
userInfo: {}
},
getters:{
isLogin(state){
return !!Object.keys(state.userInfo).length;
}
},
mutations:{
chnageUserInfo(state, data){
state.userInfo = data;
}
},
actions:{}
})
export default store;
header.vue
<template>
<el-header style="height: auto;">
<div class="header">
<div class="header_c">
<el-row type="flex" justify="start" align="middle">
<el-col :span="6">
<a href="" class="logo">
</a>
</el-col>
<el-col :span="10" :offset="2"></el-col>
<el-col :span="6" :offset="3" class="avatar-box" v-if="isLogin">
<router-link :to="{name:'sapce'}">
<el-avatar style="vertical-align: middle;" shape="square" size="medium" :src="userInfo.avatr"></el-avatar>
</router-link>
<router-link to="" class="user-name">{{userInfo.name}}</router-link>
<router-link to="" class="collection">发布菜谱</router-link>
<a href="javascript:;" @click="exit" class="collection">退出</a>
</el-col>
<el-col :span="6" :offset="3" class="avatar-box" v-if="!isLogin">
<router-link to="/index" class="user-name">登录</router-link>
<router-link to="/index" class="collection">注册</router-link>
</el-col>
</el-row>
</div>
</div>
<div class="nav-box">
<div class="nav_c">
<Menus></Menus>
</div>
</div>
</el-header>
</template>
<script>
import Menus from '@/components/menus'
import {login_out} from '@/service/api'
export default {
name: 'headers',
components: {Menus},
computed:{
isLogin(){
return this.$store.getters.isLogin
},
userInfo(){
return this.$store.state.userInfo
}
},
methods:{
exit(){
this.$confirm('真的退出吗?','提示',{
confirmButtonText:'确定',
concelButtonText:'取消',
type:'warning'
}).then(async (result)=>{
const data =await login_out()
localStorage.removeItem('token')
window.location.href='/'
})
}
}
}
</script>
<style lang="stylus">
.header
height 129px
background-color #c90000
.logo
display: block;
height: 129px;
width: 184px;
background url(https://s1.c.meishij.net/n/images/logo2.png) -15px 9px no-repeat;
.header_c, .nav_c
width 990px
margin 0 auto
.nav-box
height 60px
background-color #fff;
box-shadow 10px 0px 10px rgba(0,0,0,0.3)
.user-name
margin-left 5px
color #fff
.collection
margin-left 5px
color #fff
</style>
从vuex里面获取用户信息和isLogin,使用v-if对发布菜谱和登录来回切换