一.前言
这一篇的知识点在前面两篇的博客中就已经详细详解啦,包括如何环境搭建和如何建一个spa项目等等知识点,非常详细,大家如果有看不懂的地方可以看我前面两篇的博客,或者也可以私信问我哦~~上两篇的博客链接放下面啦!!
二.ElementUI的简介
Element的官网:
ElementUI 是一套基于 Vue.js 的桌面端 UI 组件库,它提供了丰富的组件和工具,可以帮助开发者快速构建出美观、灵活和易于维护的网页应用程序。
ElementUI 提供了众多常用的 UI 组件,例如按钮、输入框、表格、弹窗等,这些组件都经过精心设计和实现,具备良好的可定制性,可以满足各种不同场景的需求。
ElementUI 还提供了一些实用的功能组件,如表单验证、数据展示、数据交互等,能够帮助开发者简化开发流程,提高开发效率。
三.登录注册前端界面的开发
我们先来创建一个spa项目,在cmd窗口输入:
vue init webpack 项目名
· 接着下载Element依赖,在cmd窗口输入:
npm install element-ui -S
建立两个登录和注册的页面,并且使用ElementUI里的组件搭建页面以及样式
登录:
<template> <div class="login-wrap"> <el-form class="login-container"> <h1 class="title">用户登录</h1> <el-form-item label=""> <el-input type="text" v-model="username" placeholder="登录账号" autocomplete="off"></el-input> </el-form-item> <el-form-item label=""> <el-input type="password" v-model="password" placeholder="登录密码" autocomplete="off"></el-input> </el-form-item> <el-form-item> <el-button type="primary" style="width:100%;" @click="doSubmit()">提交</el-button> </el-form-item> <el-row style="text-align: center;margin-top:-10px"> <el-link type="primary">忘记密码</el-link> <el-link type="primary" @click="gotoRegister()">用户注册</el-link> </el-row> </el-form> </div> </template> <script> export default { name: 'Login', data () { return { username:"", password:"" } }, methods:{ gotoRegister(){ this.$router.push("/Register") } } } </script> <style scoped> .login-wrap { box-sizing: border-box; width: 100%; height: 100%; padding-top: 10%; background-image: /* background-color: #112346; */ background-repeat: no-repeat; background-position: center right; background-size: 100%; } .login-container { border-radius: 10px; margin: 0px auto; width: 350px; padding: 30px 35px 15px 35px; background: #fff; border: 1px solid #eaeaea; text-align: left; box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1); } .title { margin: 0px auto 40px auto; text-align: center; color: #505458; } </style>
注册:
<template> <div class="login-wrap"> <el-form class="login-container"> <h1 class="title">用户注册</h1> <el-form-item label=""> <el-input type="text" v-model="username" placeholder="登录账号" autocomplete="off"></el-input> </el-form-item> <el-form-item label=""> <el-input type="password" v-model="password" placeholder="登录密码" autocomplete="off"></el-input> </el-form-item> <el-form-item> <el-button type="primary" style="width:100%;" @click="doSubmit()">提交</el-button> </el-form-item> <el-row style="text-align: center;margin-top:-10px"> <el-link type="primary">忘记密码</el-link> <el-link type="primary" @click="gotoLogin()">用户登录</el-link> </el-row> </el-form> </div> </template> <script> export default { name: 'Register', data () { return { username:"", password:"" } }, methods:{ gotoLogin(){ this.$router.push("/") } } } </script> <style scoped> .login-wrap { box-sizing: border-box; width: 100%; height: 100%; padding-top: 10%; background-image: /* background-color: #112346; */ background-repeat: no-repeat; background-position: center right; background-size: 100%; } .login-container { border-radius: 10px; margin: 0px auto; width: 350px; padding: 30px 35px 15px 35px; background: #fff; border: 1px solid #eaeaea; text-align: left; box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1); } .title { margin: 0px auto 40px auto; text-align: center; color: #505458; } </style>
APP.vue里面的样式也添加以下:
<style> html, body { width: 100%; height: 100%; box-sizing: border-box; padding: 0px; margin: 0px; } #app { font-family: "Avenir", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; color: #2c3e50; widows: 100%; height: 100%; } </style>
下一步就是配置路由啦
import Vue from 'vue' import Router from 'vue-router' import HelloWorld from '@/components/HelloWorld' import Login from '@/views/Login' import Register from '@/views/Register' Vue.use(Router) export default new Router({ routes: [{ path: '/', name: 'Login', component: Login }, { path: '/Register', name: 'Register', component: Register } ] })
好啦,最后看效果:
三.vue axios前后端交互--- Get请求
接下来使用SSM项目构建Java后台,模拟提供一个用户登录的action地址,Vue通过请求指定的用户登录接口。
在Idea软件中写登录的后台,如何创建Idea项目,自动生成方法,Dao方法等,在之前的博客中我已经和大家介绍过了,大家可以去看,找不到的可以私信我哦~,具体的博客链接放下方啦
注册的方法:
package com.zking.ssm.service; import com.zking.ssm.model.Region; import com.zking.ssm.util.PageBean; import org.springframework.stereotype.Repository; import java.util.List; public interface IRegionService { List<Region> queryRegionPager(Region region, PageBean pageBean); List<Region> queryRegionById(Region region); }
写一个注册的web层
package com.zking.ssm.controller; import com.zking.ssm.model.Region; import com.zking.ssm.service.IRegionService; import com.zking.ssm.util.JsonResponseBody; import com.zking.ssm.util.PageBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.util.List; @RestController @RequestMapping("/region") public class RegionController { @Autowired private IRegionService regionService; @RequestMapping("/queryRegionPager") public JsonResponseBody<List<Region>> queryRegionPager(Region region, HttpServletRequest request){ try { PageBean pageBean=new PageBean(); pageBean.setRequest(request); List<Region> regions = regionService.queryRegionPager(region, pageBean); return new JsonResponseBody<>("OK",true,pageBean.getTotal(),regions); } catch (Exception e) { e.printStackTrace(); return new JsonResponseBody<>("分页查询行政区划信息失败",false,0,null); } } @RequestMapping("/queryRegionById") public JsonResponseBody<List<Region>> queryRegionById(Region region){ try { List<Region> regions = regionService.queryRegionById(region); return new JsonResponseBody<>("OK",true,0,regions); } catch (Exception e) { e.printStackTrace(); return new JsonResponseBody<>("初始化行政区划代码失败",false,0,null); } } }
写一个登录的web层:
package com.zking.ssm.controller; import com.zking.ssm.service.IUserService; import com.zking.ssm.util.JsonResponseBody; import com.zking.ssm.util.PageBean; import com.zking.ssm.vo.UserVo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.List; import java.util.Map; import com.zking.ssm.jwt.*; @Controller @RequestMapping("/user") public class UserController { @Autowired private IUserService userService; @RequestMapping("/userLogin") @ResponseBody public JsonResponseBody<?> userLogin(UserVo userVo, HttpServletResponse response){ if(userVo.getUsername().equals("admin")&&userVo.getPassword().equals("123")){ //私有要求claim // Map<String,Object> json=new HashMap<String,Object>(); // json.put("username", userVo.getUsername()); //生成JWT,并设置到response响应头中 // String jwt=JwtUtils.createJwt(json, JwtUtils.JWT_WEB_TTL); // response.setHeader(JwtUtils.JWT_HEADER_KEY, jwt); return new JsonResponseBody<>("用户登陆成功!",true,0,null); }else{ return new JsonResponseBody<>("用户名或密码错误!",false,0,null); } } @RequestMapping("/queryUserPager") @ResponseBody public JsonResponseBody<List<Map<String,Object>>> queryUserPager(UserVo userVo, HttpServletRequest request){ try { PageBean pageBean=new PageBean(); pageBean.setRequest(request); List<Map<String, Object>> users = userService.queryUserPager(userVo, pageBean); return new JsonResponseBody<>("OK",true,pageBean.getTotal(),users); } catch (Exception e) { e.printStackTrace(); return new JsonResponseBody<>("分页查询用户信息失败!",false,0,null); } } }
后台就写好啦!接下来写前台:
在此之前先来安装axios
axios是vue2提倡使用的轻量版的ajax。它是基于promise的HTTP库。它会从浏览器中创建XMLHttpRequests,与Vue配合使用非常好。
在cmd窗口中输入:
npm i axios -S
接着在Login.vue页面写逻辑代码:
<script> import axios from 'axios' export default { name: 'Login', data() { return { username: "", password: "" } }, methods: { gotoRegister() { this.$router.push("/Register") }, doSubmit() { let url = "http://localhost:8080/ssm/user/userLogin"; let params = { username: this.username, password: this.password }; axios.get(url, { params: params }).then(r => { if (r.data.success) { this.$message({ showClose: true, message: r.data.msg, type: 'success' }); }else{ this.$message.error(r.data.msg) } }).catch(e => { }); } } } </script>
注册也是一样:
<script> import axios from 'axios' export default { name: 'Register', data() { return { username: "", password: "" } }, methods: { gotoLogin() { this.$router.push("/") }, doSubmit() { let url = "http://localhost:8080/ssm/region/queryRegionPager"; let params = { username: this.username, password: this.password }; axios.get(url, { params: params }).then(r => { if (r.data.success) { this.$message({ showClose: true, message: r.data.msg, type: 'success' }); }else{ this.$message.error(r.data.msg) } }).catch(e => { }); } } } </script>
接下俩看效果吧!!
四.vue axios前后端交互--- Post请求
在写post请求之前可以发现我们可以在此基础之上做优化,将地址可以单独做一个类
action.js将接口单独领出来做一个类
将配置也可以单独领出来做一个类 http.js
/** * vue项目对axios的全局配置 */ import axios from 'axios' import qs from 'qs' //引入action模块,并添加至axios的类属性urls上 import action from '@/api/action' axios.urls = action // axios默认配置 axios.defaults.timeout = 10000; // 超时时间 // axios.defaults.baseURL = 'http://localhost:8080/j2ee15'; // 默认地址 axios.defaults.baseURL = action.SERVER; //整理数据 // 只适用于 POST,PUT,PATCH,transformRequest` 允许在向服务器发送前,修改请求数据 axios.defaults.transformRequest = function(data) { data = qs.stringify(data); return data; }; // 请求拦截器 axios.interceptors.request.use(function(config) { return config; }, function(error) { return Promise.reject(error); }); // 响应拦截器 axios.interceptors.response.use(function(response) { return response; }, function(error) { return Promise.reject(error); }); // // 路由请求拦截 // // http request 拦截器 // axios.interceptors.request.use( // config => { // //config.data = JSON.stringify(config.data); // //config.headers['Content-Type'] = 'application/json;charset=UTF-8'; // //config.headers['Token'] = 'abcxyz'; // //判断是否存在ticket,如果存在的话,则每个http header都加上ticket // // if (cookie.get("token")) { // // //用户每次操作,都将cookie设置成2小时 // // cookie.set("token", cookie.get("token"), 1 / 12) // // cookie.set("name", cookie.get("name"), 1 / 12) // // config.headers.token = cookie.get("token"); // // config.headers.name = cookie.get("name"); // // } // return config; // }, // error => { // return Promise.reject(error.response); // }); // // 路由响应拦截 // // http response 拦截器 // axios.interceptors.response.use( // response => { // if (response.data.resultCode == "404") { // console.log("response.data.resultCode是404") // // 返回 错误代码-1 清除ticket信息并跳转到登录页面 // // cookie.del("ticket") // // window.location.href='http://login.com' // return // } else { // return response; // } // }, // error => { // return Promise.reject(error.response) // 返回接口返回的错误信息 // }); export default axios;
现在开始用post的请求写一遍吧!!
先要下载一个post请求需要的在cmd中输入:
npm install qs -S
接着,前面将接口类和配置单独领出来了,所以要建立连接,需要下载一个vue-axios,在cmd中输入:
npm i vue-axios -S
再将刚刚那一串get请求换成post请求,注册也是一样
// post请求 this.axios.post(url,params).then(r => { if (r.data.success) { this.$message({ showClose: true, message: r.data.msg, type: 'success' }); }else{ this.$message.error(r.data.msg) } }).catch(e => { });
接下来看效果,和上面的get请求时一样的
五.跨域问题
在使用Vue开发前端应用时,如果前端代码部署在一个域名下,而后端接口部署在另一个域名下,就会出现跨域问题。跨域是指在浏览器中,当发起一个HTTP请求时,如果请求的目标域名、端口或协议与当前页面的域名、端口或协议不一致,就会触发跨域。
当出现跨域问题时,浏览器会阻止跨域请求,并在控制台中报错:
"Access to XMLHttpRequest at 'url' from origin 'origin' has been blocked by CORS policy.":这是最常见的跨域错误,表示浏览器拒绝了跨域请求。这是因为浏览器的同源策略限制了跨域请求。
在上面的代码中没有报跨域问题是因为,在web.xml配置文件中
也写了一个跨域工具类
package com.zking.ssm.util; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * 配置tomcat允许跨域访问 * * @author Administrator * */ public class CorsFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletResponse httpResponse = (HttpServletResponse) servletResponse; HttpServletRequest req = (HttpServletRequest) servletRequest; // Access-Control-Allow-Origin就是我们需要设置的域名 // Access-Control-Allow-Headers跨域允许包含的头。 // Access-Control-Allow-Methods是允许的请求方式 httpResponse.setHeader("Access-Control-Allow-Origin", "*");// *,任何域名 httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE"); //允许客户端发一个新的请求头jwt httpResponse.setHeader("Access-Control-Allow-Headers","responseType,Origin,X-Requested-With, Content-Type, Accept, jwt"); //允许客户端处理一个新的响应头jwt httpResponse.setHeader("Access-Control-Expose-Headers", "jwt,Content-Disposition"); //httpResponse.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); //httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE"); // axios的ajax会发两次请求,第一次提交方式为:option,直接返回即可 if ("OPTIONS".equals(req.getMethod())) { return; } filterChain.doFilter(servletRequest, servletResponse); } @Override public void destroy() { } }
好啦!,今天的分享就到这啦!!