一 快速了解

1.前言

​ EL-ADMIN 基于 Spring Boot 2.1.0 、 Spring Boot Jpa、 JWT、Spring Security、Redis、Vue、Element-UI 的前后端分离的后台管理系统, 项目采用按功能分模块的开发方式。本开发模块属于该项目前端。

2.技术栈

Vue
vue-router
axios
element ui

3.实现功能

1)登录页面

2)主页面

3)用户管理

二 初始化项目

1.创建项目

​ 使用vue-cli打开项目管理界面创建非常方便。直接在后台输入vue ui(需要vue-cli3.0以上版本)就可以打开项目管理界面。

img

​ 在选好的目录下创建新项目,包管理选择npm。

image-20220306143555037

接下来预设选择手动配置项目。

image-20220306143715649功能选择以下三个:

Babel:把JavaScript 中 es6 的新语法转化为 es5,让低端运行环境(如浏览器和 node )能够认识并执行)

Router:路由

Vuex:专为 Vue.js 应用程序开发的“状态管理模式”,采用集中式存储管理应用的所有组件的状态

image-20220306143820943

然后下一步,等待项目自动初始化完成。

2.插件安装

image-20220306163340371

3.依赖安装

image-20220306161649574

4.项目结构

`|-- public 存放静态资源,存放在该文件夹的东西不会被打包影响,而是会原封不动的输出到dist文件夹中
    |-- favicon.ico 网站图标
    |-- index.html 主页,项目入口
|-- src
    |-- api  后端请求接口文件
    |-- assets  静态资源
    |-- components  公用组件
    |-- layout  系统布局:头部、侧边栏、设置、中间内容页面
    |-- mixins  混入文件(CRUD混合模式)
    |-- router  路由配置
    |-- plugins 插件
    |-- store  vuex存放数据
    |-- utils  工具包
    |-- views  页面
    |-- app.vue  根组件
|-- main.js  入口文件
|-- .gitignore  git忽略上传的文件格式
|-- package.json 项目描述文件
|-- vue.config.js  cli配置文件

三 登录页面开发

1.引入Element-UI

有两种方式:

​ 第一种,直接在main.js中下入这三行:

image-20220306203053727

​ 第二种,直接引入element.js文件(上面三行代码抽出来放到里面)

import './plugins/element.js'

2.画登录页面

​ 这里直接把项目登录页面的样式和页面元素搬到login.vue。

image-20220306204154265

​ 然后把黄色波浪线的变量和方法都在login组件内。

​ 标签也要注释掉,因为涉及到index.vue组件。

​ 但这个时候还会存在一个问题,就是样式格式不兼容,页面全局比例不对。

​ 解决方法有两个:

​ 方法一,安装sass、sass-loader依赖(安装依赖后记得重启项目),把App.vue的样式都删掉,然后再main.js中引入准备好的全局样式index.scss。

image-20220306232415913

import './assets/styles/index.scss'

​ 方法二,不导入全局样式,直接在index.html中设置样式

body, html, #app{    
	height: 100%;
}

至此登录页面画好了,接下来就可以完成页面的底层逻辑了。

​ 补充一下:

​ .vue文件由、

image-20220306222530796

3.实现getCode()方法:获取验证码

首先需要安装axios依赖:

npm install axios

为了使axios能够全局使用,要在main.js用import导入,并且将导入的axios赋值给Vue.prototype的$axios变量(变量名可随便取)中

image-20220308131054727

注:

​ 如果想用全局注册一些数据/实用工具,可以在main.js中将变量添加到 Vue.prototype(原型)中。

	Vue.prototype.$appName = ‘My App’

​ 这样 $appName 就在所有的 Vue 实例中可用了,甚至在实例被创建之前就可以。

重启使axios依赖生效后,将getCode()方法补全

getCode(){
      //发送请求给后端,需要用到axios
      this.$axios.get('http://localhost:8000/auth/code').then(resp =>{
        this.codeUrl = resp.data.img;
        this.loginForm.uuid = resp.data.uuid;
      })
}

这样获取验证码的方法就写好了!

4.实现handleLogin()方法:处理登录请求

密码加密

​ 导入准备好的js工具文件rsaEncrypt.js,利用公钥对密码进行加密(密钥可自己生成)。image-20220308214259932

      this.loginForm.password = encrypt(this.loginForm.password);

请求处理

this.$axios.post('http://localhost:8000/auth/login',this.loginForm).then(resp => {
        this.$router.push('/dashboard');
})

​ 其中$router是访问路由实例,$router.push 方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,会回到之前的 URL。

​ push方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:

// 字符串路径
router.push('/users/eduardo')

// 带有路径的对象
router.push({ path: '/users/eduardo' })

// 命名的路由,并加上参数,让路由建立 url
router.push({ name: 'user', params: { username: 'eduardo' } })

// 带查询参数,结果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })

// 带 hash,结果是 /about#team
router.push({ path: '/about', hash: '#team' })

表单校验

将表单校验规则补全:

 loginRules:{
        username: [{required :true, trigger : 'blur' , message: '用户名不能为空'}],
        password: [{required :true, trigger : 'blur' , message: '密码不能为空'}],
        code: [{required :true, trigger : 'blur' , message: '验证码不能为空'}],
 },

required设置是否必输,trigger设置触发条件。

还需在发送请求前判断校验结果,校验通过才能发送请求。

handleLogin(){
      this.$refs.loginForm.validate( valid =>{
        if(valid){
          //如果表单校验通过,则发送登录请求
          //密码加密
          this.loginForm.password = encrypt(this.loginForm.password);
          this.$axios.post('http://localhost:8000/auth/login',this.loginForm).then(resp=>{
            this.$router.push('/dashboard');
          })
        }else alert("请按请求完善登录信息");
      });

    }

注意,这里通过this.$refs.loginForm获取的loginForm实例是由ref="loginForm"将表单实例绑定上去的。

image-20220309124947760

添加拦截器

若请求得到失败响应后,我们需要对返回响应信息进行处理,提示失败信息。

这个时候就可以用到拦截器。

这里我们把axios放在新建的request.js工具文件中导入,再在main.js中引入该文件,然后给创建的axios实例添加响应拦截器。

import axios from "axios";
import ElementUI from "element-ui";

let request = axios.create();
//添加响应拦截器
request.interceptors.response.use(response => {
    console.log("response");
    return response;//固定格式
},
    error => {
    ElementUI.Message.error("请求失败!"+error);
    return Promise.reject(error);//固定格式
    }
)

export default request;

image-20220309130429661

原先的Vue.prototype.$axios = axios也要改成Vue.prototype.$request = request,相应的this.$axios要改成this.$request

请求等待

如果后端很慢,这时候如果没有提示登录中的话,用户可能会再次点击登录,所以现在还需要实现以下请求等待的功能。

image-20220310222437797

只需要在发送请求前把loading设置为true,请求结束后再设置会false就好了。

5 实现”记住我“功能

实现”记住我“功能实际上就是实现JWT的前端功能。

数据的交互过程:用户登录 -> 后端验证登录返回 token -> 前端带上token请求后端数据 -> 后端返回数据。

img

具体要实现的:

①保存用户名密码到cookies

image-20220310211143457

②保存token到cookies

image-20220310211325325

​ 这里之前的this.loginForm也要改为user

③rememberMe判断是否要自动登录

image-20220310213214417

还需要实现判断是否要跳过登录页面,这个时候就又涉及到路由的基础知识了。

在router/index.js中添加导航守卫(NavigationGuard),用来通过跳转或取消的方式守卫导航。

router.beforeEach((to,from,next)=> {
    if(getToken()){//已登录
        if(to.name === 'Login') next('/dashboard')
        else next()
    }else if(to.path !== '/') //若不是在根路径,则自动跳转到根路劲
        next({path:'/'})
    else next()
})

“to”: 即将要进入的目标 路由对象;(这个对象中包含name,params,meta等属性)

“from”: 当前导航正要离开的路由对象;(这个对象中包含name,params,meta等属性)

“next”: Function: 确保要调用 next 方法,否则钩子就不会被 resolved。这个当中还可以传一些参数,具体可以看官方文档。

这样记住我功能就实现好了。

6 实现”注销“功能

实现注销功能需要请求后端接口删除该用户的token,同时前端Cookies也要删除该用户的token

logout(){
      //请求后端接口删除该用户的token,同时前端Cookies也要删除该用户的token
      this.$requset.delete('http://localhost:8000/auth/logout').then(res=>{
        removeToken(config.TokenKey)
        this.$Router.replace('/')
      })
}

7 实现携带token发送请求

​ 想要在每个请求头上加上token,需要使用到请求拦截器。

​ 和之前响应拦截器一样,在request.js中添加:

//添加请求拦截器
request.interceptors.request.use(config => {
    console.log('请求拦截!')
    if(getToken()){
        config.heads['Authorization'] = getToken()
    }
    return config
},
    error => {
        return Promise.reject(error)
    })

由于axios默认的请求格式就是application/json, 所以这里是不用设置的。

注:一定要记得return!因为use接受两个函数作为参数,那么这两个函数就必须要有返回值。

8 认证失败或过期的处理

​ 一般,认证失败后,需要做的是自动注销并且跳转至登录页面。

​ 首先,我们可以把登录相关的方法抽出来封装到login.js中。

import {removeToken} from "./auth";
import Config from '@/setting';
import router from "@/router";
import request from "./request";

export function logout(){
    request.delete('http://localhost:8000/auth/logout').then(res =>{
        removeToken(Config.TokenKey)
        router.replace('/')
    })
}

然后在响应拦截器中添加判断认证失败(401错误码)的操作,如果是认证失败就直接进行注销。

image-20220310224242852

到这里登录页面的基本功能就已经都完成了!

Logo

前往低代码交流专区

更多推荐