添加Element-UI依赖
安装依赖
npm i element-ui -S
导入依赖及使用
在main.js中导入Element-UI依赖并使用。
import ElementUI, {Message} from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';Vue.use(ElementUI,{size:"small"});
页面组件
主程序页面组件(App.vue)
<template> <div id="app"> <router-view/> div>template>
在主程序页面组件中,只保留一个路由视图()对象,通过访问路径(url)匹配呈现的VUE组件,渲染至路由视图对象。
主程序入口(main.js)
import Vue from 'vue'import App from './App.vue'import router from './router'import ElementUI from 'element-ui';import 'element-ui/lib/theme-chalk/index.css';Vue.config.productionTip = falseVue.use(ElementUI,{size:"small"});new Vue({ router, render: h => h(App)}).$mount('#app')
在主程序入口处导入VUE、App(主程序页面组件)、router(VUE路由对象)、ElementUI(ElementUI类库)、ElementUI样式。通过Vue.use(ElementUI)使用ElementUI组件。在VUE实例中配置VUE路由(router)对象,并指定渲染展现的容器。
页面路由控制(router/index.js)
import Vue from 'vue'import VueRouter from 'vue-router'import Login from '../views/Login.vue'Vue.use(VueRouter)const routes = [ { path: '/', name: 'Login', component: Login, hidden:true }]const router = new VueRouter({ routes})export default router
在VUE路由组件中通过import分别导入VUE类库、VUE路由对象(vue-router)、登录组件(Login.vue)并通过Vue.use(VueRouter)使用VUE路由对象。
通过const定义VUE路由对象(const定义的变量不可修改,必须初始化),path为页面访问路径,name为组件名称,component为通过PATH可以访问到的对应组件,hidden为是否隐藏组件。
在index.js中通过export default router定义一个VUE路由对象变量,通过const router = new VueRouter({
routes})初始化VUE路由对象实例,并配置访问路径与VUE组件转发规则。
登录组件(views/Login.vue)
<template> <div> <el-form :rules="rules" ref="loginForm" :model="loginForm" class="loginContainer"> <h3 class="loginTitle">系统登录h3> <el-form-item prop="username"> <el-input size="normal" type="text" v-model="loginForm.username" auto-complete="off" placeholder="请输入用户名">el-input> el-form-item> <el-form-item prop="password"> <el-input size="normal" type="password" v-model="loginForm.password" auto-complete="off" placeholder="请输入密码" @keydown.enter.native="submitLogin">el-input> el-form-item> <el-button size="normal" type="primary" style="width: 100%;" @click="submitLogin">登录el-button> el-form> div>template><script>export default { name: "Login", data() { return { //配置登录表单属性值 loginForm: { username: 'admin', password: '123' }, //配置校验规则(required:是否必填,message:校验未通过提示信息,trigger:触发校验规则事件) rules: { username: [{required: true, message: '请输入用户名', trigger: 'blur'}], password: [{required: true, message: '请输入密码', trigger: 'blur'}] } } }, //配置表单事件触发方法 methods: { //表单登录提交事件($refs.loginForm:通过$refs.ref属性值获取需校验表单) submitLogin() { this.$refs.loginForm.validate((valid) => { if (valid) { this.postKeyValueRequest("/doLogin",this.loginForm).then(resp=>{ if(resp) { this.$message.success(JSON.stringify(resp.obj)); //将登录用户信息临时缓存于前端页面 window.sessionStorage.setItem("user",JSON.stringify(resp.obj)); /** 获取targetPath判断用户是否是匿名访问组件,如果为/或undefined,说明为正常登录,跳转至欢迎页, 否则跳转至匿名访问组件页面 */ let targetPath=this.$route.query.redirect; this.$router.replace((targetPath=='/'||targetPath==undefined)?'/home':targetPath); } }) } else { this.$message.error('表单校验未通过'); return false; } }); } } }script><style> .loginContainer { border-radius: 15px; background-clip: padding-box; margin: 180px auto; width: 350px; padding: 15px 35px 15px 35px; background: #fff; border: 1px solid #eaeaea; box-shadow: 0 0 25px #cac6c6; } .loginTitle { margin: 15px auto 20px auto; text-align: center; color: #505458; } .loginRemember { text-align: left; margin: 0px 0px 15px 0px; }style>
登录操作
表单校验
在vue实例中的data属性内配置表单校验内容和表单校验规则。
data() { return { //配置登录表单属性值 loginForm: { username: 'admin', password: '123' }, //配置校验规则(required:是否必填,message:校验未通过提示信息,trigger:触发校验规则事件) rules: { username: [{required: true, message: '请输入用户名', trigger: 'blur'}], password: [{required: true, message: '请输入密码', trigger: 'blur'}] } } }
在VUE模板中定义登录表单及注册登录事件。
<el-form :rules="rules" ref="loginForm" :model="loginForm" class="loginContainer"> <h3 class="loginTitle">系统登录h3> <el-form-item prop="username"> <el-input size="normal" type="text" v-model="loginForm.username" auto-complete="off" placeholder="请输入用户名">el-input> el-form-item> <el-form-item prop="password"> <el-input size="normal" type="password" v-model="loginForm.password" auto-complete="off" placeholder="请输入密码" @keydown.enter.native="submitLogin">el-input> el-form-item> <el-button size="normal" type="primary" style="width: 100%;" @click="submitLogin">登录el-button> el-form>
登录事件
//配置表单事件触发方法 methods: { //表单登录提交事件($refs.loginForm:通过$refs.ref属性值获取需校验表单) submitLogin() { this.$refs.loginForm.validate((valid) => { if (valid) { this.postKeyValueRequest("/doLogin",this.loginForm).then(resp=>{ //已经在api.js里面处理过服务端响应信息,这里的resp为后端接口响应数据信息 if(resp) { this.$message.success(JSON.stringify(resp.obj)); //将登录用户信息临时缓存于前端页面 window.sessionStorage.setItem("user",JSON.stringify(resp.obj)); /** 获取targetPath判断用户是否是匿名访问组件,如果为/或undefined,说明为正常登录,跳转至欢迎页, 否则跳转至匿名访问组件页面 */ let targetPath=this.$route.query.redirect; /** *通过$router获取vue路由对象(router为main.js配置的VUE路由对象名称) *replace:对转发页面进行替换,无法通过后退按钮返回上一页,push:可通过后退按钮返回上一页 */ this.$router.replace((targetPath=='/'||targetPath==undefined)?'/home':targetPath); } }) } else { this.$message.error('表单校验未通过'); return false; } }); }
在VUE实例method属性中添加登录事件处理函数(回车键及单击按钮事件提交表单,doLogin为SpringSecurity中表单提交默认处理url),当表单校验通过后执行相关操作。
前后端接口对接
安装网络请求工具
在VUE2.x中,通过axios发送网络请求。
npm install axios
前端请求封装(utils/api.js)
/** * 导入相关组件 * axios:用于vue发送ajax请求 * {Message}:用于消息提示 * router:用于路由 */import axios from 'axios'import {Message} from 'element-ui'import router from '../router'/** *响应成功进入data,响应失败进入error */axios.interceptors.response.use(success=>{ //逻辑错误(success.status为http请求状态码,success.data.status为后台封装响应码) if (success.status && success.status == 200 && success.data.status == 500) { Message.error({message: success.data.message}) return; } if(success.data.message) { Message.success({message:success.data.message}); } return success.data;},error=>{ if (error.response.status == 504 || error.response.status == 404) { Message.error({message: '未找到服务器'}) } else if (error.response.status == 403) { Message.error({message: '权限不足,请联系管理员'}) } else if (error.response.status == 401) { //状态码为401(后端服务重启,页面session过期),利用router转发至登录页 Message.error({message: '尚未登录,请登录'}) router.replace('/'); } else { if (error.response.data.message) { Message.error({message: error.response.data.message}) } else { Message.error({message: '未知错误!'}) } } return;})let base='';export const postKeyValueRequest = (url, params) => { return axios({ method: 'post', url: `${base}${url}`, data: params,//登录表单输入参数 //对登录表单输入参数进行转换(登录表单输入参数为key:value.SpringSecurity登录校验默认不支持json数据格式,需转换为字符串) transformRequest: [function (data) { let ret = ''; /** * i:登录表单组件名称 * data[i]:登录表单组件名称对应参数 */ for (let i in data) { ret += encodeURIComponent(i) + '=' + encodeURIComponent(data[i]) + '&' } return ret; }], headers: { 'Content-Type': 'application/x-www-form-urlencoded' } });}export const postRequest = (url, params) => { return axios({ method: 'post', url: `${base}${url}`, data: params });}export const putRequest = (url, params) => { return axios({ method: 'put', url: `${base}${url}`, data: params });}export const getRequest = (url, params) => { return axios({ method: 'get', url: `${base}${url}`, data: params });}export const deleteRequest = (url, params) => { return axios({ method: 'delete', url: `${base}${url}`, data: params })}
在utils/api.js中,主要对处理响应信息及发送前端请求进行封装。
处理响应信息
/** *利用axios响应拦截器(axios.interceptors.response)对请求响应进行处理 *响应成功进入success回调函数,响应失败进入error回调函数 */axios.interceptors.response.use(success=>{ //逻辑错误(success.status为http响应码,success.data.status为后端接口封装响应码信息) if (success.status && success.status == 200 && success.data.status == 500) { Message.error({message: success.data.message}) return; } if(success.data.message) { Message.success({message:success.data.message}); } return success.data;},error=>{ if (error.response.status == 504 || error.response.status == 404) { Message.error({message: '未找到服务器'}) } else if (error.response.status == 403) { Message.error({message: '权限不足,请联系管理员'}) } else if (error.response.status == 401) { //状态码为401(后端服务重启,页面session过期),利用router转发至登录页 Message.error({message: '尚未登录,请登录'}) router.replace('/'); } else { if (error.response.data.message) { Message.error({message: error.response.data.message}) } else { Message.error({message: '未知错误!'}) } } return;})
前端请求封装
let base='';/***用于发送登录请求*url:请求路径*params:输入参数*/export const postKeyValueRequest = (url, params) => { return axios({ method: 'post', url: `${base}${url}`, data: params, /** *利用transformRequest对登录表单参数进行转换 */ transformRequest: [function (data) { let ret = ''; /** *对表单数据进行遍历并叠加至ret变量,并利用encodeURIComponent将字符串作为URI组件编码 *i表示登录表单参数的key,data[i]表示登录表单参数的value */ for (let i in data) { ret += encodeURIComponent(i) + '=' + encodeURIComponent(data[i]) + '&' } return ret; }], headers: { 'Content-Type': 'application/x-www-form-urlencoded' } });}export const postRequest = (url, params) => { return axios({ method: 'post', url: `${base}${url}`, data: params });}export const putRequest = (url, params) => { return axios({ method: 'put', url: `${base}${url}`, data: params });}export const getRequest = (url, params) => { return axios({ method: 'get', url: `${base}${url}`, data: params });}export const deleteRequest = (url, params) => { return axios({ method: 'delete', url: `${base}${url}`, data: params })}
请求代理配置(vue.config.js)
在开发环境中,我们需要通过nodejs在前后端分离架构中进行请求转发。前端将请求转发至nodejs代理对象,nodejs代理对象转发至后端;后端将响应结果转发至nodejs代理对象,nodejs代理对象将响应结果转发至前端。
let proxyObj={};/* 代理对象代理至后端配置 ws:是否开启websocket target:代理至后端项目地址 changeOrigin:表示是否跨域 pathRewrite:target访问地址替换(此处不替换) */proxyObj['/']={ ws:false, target: 'http://localhost:8081', changeOrigin: true, pathRewrite:{ '^/':'' }}/* 前端导入配置 host:配置导入ip地址 port:配置导入端口 proxy:配置前端访问代理兑现通过 */module.exports={ devServer:{ host:'localhost', port:8080, proxy:proxyObj }}
页面路由
在登录成功回调函数中,对页面进行路由转发。
/** 获取targetPath判断用户是否是匿名访问组件,如果为/或undefined,说明为正常登录,跳转至欢迎页, 否则跳转至匿名访问组件页面 */ let targetPath=this.$route.query.redirect; /** *通过$router获取vue路由对象(router为main.js配置的VUE路由对象名称) *replace:对转发页面进行替换,无法通过后退按钮返回上一页,push:可通过后退按钮返回上一页 */ this.$router.replace((targetPath=='/'||targetPath==undefined)?'/home':targetPath);