提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
1. 登录状态保持
如果服务器和客户端同源,建议可以使用cookie或者session来保持登录状态 如果客户端和服务器跨域了,建议使用token进行维持登录状态。
2. 登录逻辑
在登录页面输入账号和密码进行登录,将数据发送给服务器 服务器返回登录的结果,登录成功则返回数据中带有token 客户端得到token并进行保存,后续的请求都需要将此token发送给服务器,服务器会验证token以保证用户身份。
在components文件夹中新建Login.vue组件,添加template,script,style标签,style标签中的scoped可以防止组件之间的样式冲突,没有scoped则样式是全局的
在router.js中导入组件并设置规则
const router = new Router({
routes: [
{ path: '/', redirect: '/login' },
{ path: '/login', component: Login }
]
})
在App.vue中添加路由占位符
<template>
<div id="app">
<!-- 路由占位符 -->
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
### 1.2添加element-ui的表单组件
在plugins文件夹中打开element.js文件,进行elementui的按需导入
```javascript
import Vue from 'vue'
import { Button,Form, FormItem, Input } from 'element-ui'
Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
<template>
<div class="login_container">
<div class="login_box">
<!-- 头像区域 -->
<div class="avater_box">
<img src="../assets/logo.png" alt="">
</div>
<!-- 表单区域 -->
<el-form ref="loginFormRef" :model="loginForm" :rules="loginFormRules" label-width="0px" class="login_form">
<!-- 用户名 -->
<el-form-item prop="username">
<el-input v-model="loginForm.username" prefix-icon="iconfont icon-user"></el-input>
</el-form-item>
<!-- 密码 -->
<el-form-item prop="password">
<el-input v-model="loginForm.password" prefix-icon="iconfont icon-3702mima"></el-input>
</el-form-item>
<!-- 按钮区域 -->
<el-form-item class="btns">
<el-button type="primary" @click="login">登录</el-button>
<el-button type="info" @click="resetLoginForm">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
复制素材中的fonts文件夹到assets中,在入口文件main.js中导入css文件
import './assets/fonts/iconfont.css'
//然后直接在Login.vue页面直接使用
<el-input prefix-icon="iconfont icon-3702mima"></el-input>
1).给添加属性:rules=“rules”,rules是一堆验证规则,定义在script中
<el-form ref="loginFormRef" :model="loginForm" :rules="loginFormRules" label-width="0px" class="login_form">
2).在script中添加rules:
// 表单的校验规则对象
loginFormRules: {
// 验证用户名是否合法
username: [
{ require: true, message: "请输入登录名称", trigger: "blur"},
{ min: 3, max: 10, message: '用户名长度在 3 到 10 个字符', trigger: 'blur'}
],
//验证密码是否合法
password: [
{ require: true, message: "请输入密码", trigger: "blur"},
{ min: 6, max: 15, message: '长度在 6 到 15 个字符', trigger: 'blur'}
]
}
打开main.js,import axios from ‘axios’; 设置请求的根路径:axios.defaults.baseURL = ‘http://127.0.0.1:8888/api/private/v1/’; 挂载axios:Vue.prototype.$http = axios;
import axios from 'axios'
// 配置请求根路径
axios.defaults.baseURL='http://127.0.0.1:8888/api/private/v1/'
//请求在到达服务器之前,先会调用use中的这个回调函数来添加请求头信息
Vue.prototype.$http=axios
在plugins文件夹中打开element.js文件,进行elementui的按需导入 import {Message} from ‘element-ui’ 进行全局挂载:
import Vue from 'vue'
import { Button,Form, FormItem, Input,Message } from 'element-ui'
Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
Vue.prototype.$confirm=MessageBox.confirm
登录按钮
登录成功之后,需要将后台返回的token保存到sessionStorage中 操作完毕之后,需要跳转到/home
login(){
// 点击登录时先调用validate方法验证表单是否有误
this.$refs.loginFormRef.validate(async valid => {
if(!valid) { return }
// 发送请求进行登录
const { data: res} = await this.$http.post("login",this.loginForm)
if(res.meta.status !== 200) return this.$message.error("登录失败" + res.meta.msg)
this.$message.success("登陆成功")
// 1.将登陆成功之后的token,保存到客户端的sessionStorage中
// 1.1项目中出了登录之外的其他api接口,必须在登录之后才能访问
// 1.2token只应在当前网站打开期间生效,所以将token保存在sessionStorage中
window.sessionStorage.setItem("token",res.data.token)
// 2.通过编程式导航跳转到后台主页,路由地址是\home
this.$router.push("/home")
})
}
重置按钮
resetLoginForm(){
this.$refs.loginFormRef.resetFields()
},
```
添加一个组件Home.vue,并为之添加规则
<template>
<div>
this is home
<el-button type="info" @click="logout"> 退出 </el-button>
</div>
</template>
<script>
export default {
methods: {
logout() {
window.sessionStorage.clear()
this.$router.push('/login')
}
}
}
</script>
<style lang='less' scoped>
</style>
添加路由规则
const router = new Router({
routes: [
{ path: '/', redirect: '/login' },
{ path: '/login', component: Login },
{ path: '/home', component: Home }
]
})
添加路由守卫 如果用户没有登录,不能访问/home,如果用户通过url地址直接访问,则强制跳转到登录页面 打开router.js
import Vue from 'vue'
import Router from 'vue-router'
import Login from './components/Login.vue'
import Home from './components/Home.vue'
Vue.use(Router)
const router = new Router({
routes: [
{ path:'/', redirect:'/login'},
{ path:'/login' , component:Login },
{ path:'/home' , component:Home}
]
})
//挂载路由导航守卫,to表示将要访问的路径,from表示从哪里来,next是下一个要做的操作
router.beforeEach((to,from,next)=>{
if(to.path === '/login')
return next();
//获取token
const tokenStr = window.sessionStorage.getItem('token');
if(!tokenStr)
return next('/login');
next();
})
export default router
实现退出功能 在Home组件中添加一个退出功能按钮,给退出按钮添加点击事件,添加事件处理代码如下:
export default {
methods:{
logout(){
window.sessionStorage.clear();
this.$router.push('/login');
}
}
}
<template>
<div class="login_container">
<!-- 登录盒子 -->
<div class="login_box">
<!-- 头像 -->
<div class="avatar_box">
<img src="../assets/logo.png" alt="">
</div>
<!-- 登录表单 -->
<el-form :model="loginForm" ref="LoginFormRef" :rules="loginFormRules" label-width="0px" class="login_form">
<!-- 用户名 -->
<el-form-item prop="username">
<el-input v-model="loginForm.username" prefix-icon="iconfont icon-user" ></el-input>
</el-form-item>
<!-- 密码 -->
<el-form-item prop="password">
<el-input type="password" v-model="loginForm.password" prefix-icon="iconfont icon-3702mima"></el-input>
</el-form-item>
<!-- 按钮 -->
<el-form-item class="btns">
<el-button type="primary" @click="login">登录</el-button>
<el-button type="info" @click="resetLoginForm">重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
//添加行为,
methods: {
//添加表单重置方法
resetLoginForm() {
//this=>当前组件对象,其中的属性$refs包含了设置的表单ref
// console.log(this)
this.$refs.LoginFormRef.resetFields()
},
login() {
//点击登录的时候先调用validate方法验证表单内容是否有误
this.$refs.LoginFormRef.validate(async valid => {
console.log(this.loginFormRules)
//如果valid参数为true则验证通过
if (!valid) {
return
}
//发送请求进行登录
const { data: res } = await this.$http.post('login', this.loginForm)
// console.log(res);
if (res.meta.status !== 200) {
return this.$message.error('登录失败:' + res.meta.msg) //console.log("登录失败:"+res.meta.msg)
}
this.$message.success('登录成功')
console.log(res)
//保存token
window.sessionStorage.setItem('token', res.data.token)
// 导航至/home
this.$router.push('/home')
})
}
}
}
</script>
<style lang="less" scoped>
.login_container {
background-color: #2b5b6b;
height: 100%;
}
.login_box {
width: 450px;
height: 300px;
background: #fff;
border-radius: 3px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
.avatar_box {
height: 130px;
width: 130px;
border: 1px solid #eee;
border-radius: 50%;
padding: 10px;
box-shadow: 0 0 10px #ddd;
position: absolute;
left: 50%;
transform: translate(-50%, -50%);
background-color: #fff;
img {
width: 100%;
height: 100%;
border-radius: 50%;
background-color: #eee;
}
}
}
.login_form {
position: absolute;
bottom: 0;
width: 100%;
padding: 0 20px;
box-sizing: border-box;
}
.btns {
display: flex;
justify-content: flex-end;
}
</style>