登录/退出功能
登录概述
- 登录业务流程
- 在登录页面输入用户名和密码
- 调用后台接口进行验证
- 通过验证之后,根据后台的响应状态跳转到项目主页
- 登录业务的相关技术点
- http是无状态的
- 通过cookie 在客户端记录状态(不存在跨域问题)
- 通过session在服务器端记录状态(不存在跨域问题)
- 通过token方式维持状态(存在跨域问题)
登录 – token原理分析
登录功能实现
登录页面的布局
通过Element-UI
组件实现布局
- el-form
- el-form-item
- el-input
- el-button
- 字体图标
-
在终端命令行中输入
git checkout -b login
,创建新的z子分支login -
用
git branch
查看一共有多少个分支 -
创建登录组件
- 在component文件下添加
Login.vue
,里面添加
<template> <div> 登录组件 </div> </template> <script> export default { name: "Login" } </script> <style lang="less" scoped> </style>
- 在
index.js
文件下写入
import Login from "../components/Login"; const routes = [ { path: '/', redirect:'/login' }, { path:'/login', component: Login } ]
- 在component文件下添加
-
登录组件布局
- 安装依赖
less-loader
和less
- 在src/asserts创建cdd文件夹,创建全局样式
global.css
/* 全局样式表 */ html, body, #app { height: 100%; margin: 0; padding: 0; }
- 在Login.vue中写入登录样式
<template> <div class="login_container"> <div class="login_box"> <!-- 头像区域 --> <div class="avatar_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" type="password"></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> <script> export default { data() { return { } }, methods: { } } </script> <style lang="less" scoped> .login_container { background-color: #2b4b6b; height: 100%; } .login_box { width: 450px; height: 300px; background-color: #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>
- 安装依赖
-
在引入组件的时候,要先导入组件
- 在
plugins/element.js
文件下
import Vue from 'vue' import { Button, Form, FormItem, Input } from 'element-ui' Vue.use(Button) Vue.use(Form) Vue.use(FormItem) Vue.use(Input)
- 在
-
在
main.js
文件下导入字体图标
import './assets/fonts/iconfont.css'
- 表单数据绑定
// 这是登录表单的数据绑定对象
loginForm: {
username: 'admin',
password: '123456'
},
- 表单数据验证
// 这是表单的验证规则对象
loginFormRules: {
// 验证用户名是否合法
username: [
{ required: true, message: '请输入登录名称', trigger: 'blur' },
{ min: 3, max: 10, message: '长度在 3 到 10 个字符', trigger: 'blur' }
],
// 验证密码是否合法
password: [
{ required: true, message: '请输入登录密码', trigger: 'blur' },
{ min: 6, max: 15, message: '长度在 6 到 15 个字符', trigger: 'blur' }
]
}
- 表单重置
// 点击重置按钮,重置登录表单
resetLoginForm() {
// console.log(this);
this.$refs.loginFormRef.resetFields()
},
- 判断是否发起请求时,在
main.js
添加根路径
import axios from 'axios'
//配置请求的根路径
axios.defaults.baseURL='http://127.0.0.1:8888/api/private/v1/'
Vue.prototype.$http = axios
//登录前的预验证
login() {
this.$refs.loginFormRef.validate(async valid => {
if (!valid) return
const { data: res } = await this.$http.post('login', this.loginForm)
})
}
-
配置弹框提示
- 在
element.js
下导入弹框提示组件并且挂载Vue上
import {Message} from "element-ui" Vue.prototype.$message = Message
- 修改
Login.vue
if (res.meta.status !== 200) return this.$message.error('登录失败!') this.$message.success('登录成功')
- 在
实现登录
- 登录成功后的行为
- 通过 axios 调用登录验证接口
- 登录成功之后保持用户 token 信息
- 跳转到项目主页
- 在components文件夹下创建
Home.vue
- 在
main.js
加入
import Home from "../components/Home";
{
path: '/home',
component: Home
}
this.$message.success('登录成功')
// 1. 将登录成功之后的 token,保存到客户端的 sessionStorage 中
// 1.1 项目中出了登录之外的其他API接口,必须在登录之后才能访问
// 1.2 token 只应在当前网站打开期间生效,所以将 token 保存在 sessionStorage 中
window.sessionStorage.setItem('token', res.data.token)
// 2. 通过编程式导航跳转到后台主页,路由地址是 /home
this.$router.push('/home')
路由导航守卫控制访问权限
如果用户没有登录,但是直接通过URL访问特定页面,需要重新导航到登录页面。
- 在
router.js
挂载路由导航守卫
// 为路由对象,添加 beforeEach 导航守卫
router.beforeEach((to, from, next) => {
// 如果用户访问的登录页,直接放行
if (to.path === '/login') return next()
// 从 sessionStorage 中获取到 保存的 token 值
const tokenStr = window.sessionStorage.getItem('token')
// 没有token,强制跳转到登录页
if (!tokenStr) return next('/login')
next()
})
to
将要访问的路径from
代表从哪个路径跳转而来next
是一个函数,表示放行next()
放行next("/login")
强制跳转
退出
退出功能实现原理
基于 token 的方式实现退出比较简单,只需要销毁本地的 token 即可。这样,后续的请求就不会携带token ,必须重新登录生成一个新的 token 之后才可以访问页面
// 清空token
window.sessionStorage.clear()
// 跳转到登录页
this.$router.push('/login')
处理语法警告问题
在根目录下创建.prettierrc
{
//移除分号
"semi": false,
//单引号
"singleQuote": true
}