spa项目开发之登录注册(vue)
转载请标明出处:https://blog.csdn.net/men_ma/article/details/106847165.
本文出自 不怕报错 就怕不报错的小猿猿 的博客
spa项目开发之登录注册(vue)
- 前言
- 1.本次的目标
- 2.spa项目完成登录注册布局
- 2.1 第一步:
- 2.2 第二步:
- 2.3 第三步:
- 2.4 第四步:
- 2.5 第五步:
- 2.6 看效果:
- 3.Spa项目完成登录功能
- 4.ajax 跨域问题
- 4.1 什么叫跨域?
- 5.axios 的 get/post 的区别( qs )
- 6.This 指针带来的变量污染
前言
今日分享的是spa项目开发之登录注册,在这之前,我们要先搭建一个spa的项目,如何去搭建spa的项目呢?本篇知识与spa项目的搭建息息相关,建立在此基础之上,本博主在此附上搭建spa项目的博客链接,如下
链接: 如何使用Vue-cli搭建SPA项目?&如何在spa项目中使用路由?&嵌套路由的使用.
搭建好的spa项目结构图:

部分工具包的介绍:

另外本次目标需要两台服务器,前台(8088端口号)跟后台(8080端口号),所以需要Tomcat启动后台的服务器(eclipse),后台的项目搭建建立在maven项目基础之上
1.本次的目标
1、spa项目完成登录注册布局
2、Spa项目完成登录功能
3、 ajax 跨域问题
4、axios 的 get/post 的区别( qs )
5、T his 指针带来的变量污染
整个spa项目的结构图(贴出来):
先安装一下开发模块(命令):
npm install element-ui -S //为了显示样式,跟导入js差不多
npm install axios -S //需要ajax必须安装
npm install qs -S //为了解决get和post的区别
npm install vue-axios -S //是vue2提倡使用的轻量版的ajax
注意:一定要在项目的根路径下安装执行命令


查看上述安装是否成功安装到spa项目中去:

2.spa项目完成登录注册布局
2.1 第一步:
在这里需要用到element-ui,所以需要在main.js中导入,例如用到路由则导入路由
//导入命令
import 'element-ui/lib/theme-chalk/index.css'//使用elementUI
Vue.use(ElementUI)

2.2 第二步:
将如下css 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>
如下所示:

2.3 第三步:
数据库:

后台逻辑代码(关键类)UserAction.java:
public class UserAction extends BaseAction implements ModelDriven<User>{private UserBiz userBiz;private User user = new User();public UserBiz getUserBiz() {return userBiz;}public void setUserBiz(UserBiz userBiz) {this.userBiz = userBiz;}public String login() {ObjectMapper om = new ObjectMapper();JsonData jsonData = null;try {if(StringUtils.isBlank(user.getUname()) || StringUtils.isBlank(user.getPwd())) {jsonData = new JsonData(0, "用户或者密码为空", user);}else {User u = this.userBiz.login(user);
// Map<String, Object> claims = new HashMap<String, Object>();
// claims.put("uname",user.getUname());
// claims.put("pwd", user.getPwd());
// String jwt = JwtUtils.createJwt(claims, JwtUtils.JWT_WEB_TTL);
// response.setHeader(JwtUtils.JWT_HEADER_KEY, jwt);jsonData = new JsonData(1, "登录成功", u);}} catch (Exception e) {e.printStackTrace();jsonData = new JsonData(0, "用户或者密码错误", user);}finally {try {ResponseUtil.write(response, om.writeValueAsString(jsonData));} catch (Exception e) {e.printStackTrace();}}return null;}public String getAsyncData() {ObjectMapper om = new ObjectMapper();try {Thread.sleep(6000);ResponseUtil.write(response, om.writeValueAsString("http://www.javaxl.com"));} catch (Exception e) {e.printStackTrace();}return null;}@Overridepublic User getModel() {return user;}
}
Login.vue:
**注意:**后台的属性名与前台的v-model绑定文本框的数据的属性名一定要一致,不然无效
<template><div class="login-wrap"><el-form :model="ruleForm" ref="ruleForm" label-width="100px" class="demo-ruleForm login-container"><h3 style="text-align: center;">用户登录</h3><el-form-item label="用户名" prop="unameuname"><el-input type="uname" v-model="ruleForm.uname" autocomplete="off"></el-input></el-form-item><el-form-item label="密码" prop="pwd"><el-input type="pwd" v-model="ruleForm.pwd" autocomplete="off"></el-input></el-form-item><el-form-item><el-row><el-col :span="24"><div class="grid-content bg-purple-dark"><el-button type="primary" style="width: 100%;" @click="doSub">提交</el-button></div></el-col></el-row><el-row><el-col :span="12"><div class="grid-content bg-purple"><el-link type="success" @click="toReg">用户注册</el-link></div></el-col><el-col :span="12"><div class="grid-content bg-purple-light"><el-link type="success">忘记密码</el-link></div></el-col></el-row></el-form-item></el-form></div>
</template><script>/* import qs from 'qs' */ //相当于把js文件导进来,当不用http.js工具类时需要导入export default {data() {return {ruleForm: {uname: 'zs',pwd: '123'}};},methods: {toReg() {this.$router.push({path: '/Reg'});},doSub() {//用工具类时的方法let url = this.axios.urls.SYSTEM_USER_DOLOGIN;//不用工具类时的方法//let url = 'http://localhost:8080/T216_SSH/vue/userAction_login.action';console.log(url);//post方式提交//这个this代表vue的实例this.axios.post(url, this.ruleForm).then((response) => {console.log(response);if (response.data.code == 1) {//这个this代表这个方法function(response)(用es6的箭头函数解决this指针带来的变量污染)this.$message({//登录成功消息提示message: response.data.msg,type: 'success'});} else {this.$message({//用户或密码错误消息提示message: response.data.msg,type: 'warning'});} //alert(111)//get方式提交/* this.axios.get(url, {params:this.ruleForm}).then((response) => {console.log(response);if (response.data.code == 1) {//这个this代表这个方法function(response)(用es6的箭头函数解决this指针带来的变量污染)this.$message({//登录成功消息提示message: response.data.msg,type: 'success'});} else {this.$message({//用户或密码错误消息提示message: response.data.msg,type: 'warning'});} */}).catch(function(error) {console.log(error);});}}}
</script><style scoped>.login-wrap {box-sizing: border-box;width: 100%;height: 100%;padding-top: 10%;background-image: url(data:image/svg+xml;base64, //这里有一个图片地址,特别长,为了博主给去掉了;/* 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>
2.4 第四步:
加入Login.vue组件到index.js中:
//导入vue文件
import Login from '@/views/Login'
import Reg from '@/views/Reg'//配置路由线路{path: '/',name: 'Login',component: Login},{path: '/Login',name: 'Login',component: Login},{path: '/Reg',name: 'Reg',component: Reg}

2.5 第五步:
Reg.vue:复制一下Login,vue,修改一下调用的方法就好了


2.6 看效果:
第一步:

第二步:

第三步:

3.Spa项目完成登录功能
第一步:导入工具包(两个类)
action.js:
/*** 对后台请求的地址的封装,URL格式如下:* 模块名_实体名_操作*/
export default {'SERVER': 'http://localhost:8080/T216_SSH', //服务器'SYSTEM_USER_DOLOGIN': '/vue/userAction_login.action', //用户登陆'SYSTEM_USER_DOREG': '/vue/userAction_reg.action', //用户注册'SYSTEM_MENU_TREE': '/vue/treeNodeAction.action', //左侧树形菜单加载'SYSTEM_ARTICLE_LIST': '/vue/articleAction_list.action', //文章列表'SYSTEM_ARTICLE_ADD': '/vue/articleAction_add.action', //文章新增'SYSTEM_ARTICLE_EDIT': '/vue/articleAction_edit.action', //文章修改'SYSTEM_ARTICLE_DEL': '/vue/articleAction_del.action', //文章删除'SYSTEM_USER_GETASYNCDATA': '/vue/userAction_getAsyncData.action', //vuex中的异步加载数据'getFullPath': k => { //获得请求的完整地址,用于mockjs测试时使用return this.SERVER + this[k];}
}
http.js:
/*** vue项目对axios的全局配置*/
import axios from 'axios'
import qs from 'qs'//引入action模块,并添加至axios的类属性urls上
import action from '@/api/action'
axios.urls = action //action相当于action.js// 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) {// var jwt = window.vm.$store.getters.getJwt;// config.headers['jwt'] = jwt;return config;
}, function(error) {return Promise.reject(error);
});// 响应拦截器
axios.interceptors.response.use(function(response) {// debugger;// var jwt = response.headers['jwt'];// if(jwt){// window.vm.$store.commit('setJwt',{jwt:jwt});// }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;
第二步:导入api(main.js)
//导入import axios from '@/api/http' //用了工具类时
import VueAxios from 'vue-axios' //使用
Vue.use(VueAxios,axios)

第三步:利用axios的get/post的提交(前面Login.vue已附上)

第四步:运行结果(控制台)一定要记得启动后台Tomcat的服务器


4.ajax 跨域问题
4.1 什么叫跨域?
url地址:协议+ip+port+项目(四部分组成)
例如:
http://localhost:8080/T216_SSH/vue/treeNodeAction.action
只要四个部分中有一个部分不一样就属于跨域
例如:http://localhost:8080/T216_SSHhttp://localhost:8080/T216_SSH2http://localhost:8088/T216_SSHhttp://192.168.122.11:8080/T216_SSHhttps://localhost:8088/T216_SSH此上地址是属于跨域
附录一:ES6的语法箭头函数
doSomething(function(a){…});
doSomething((a)=>{});
过滤器CorsFilter.java
/*** 配置tomcat允许跨域访问* * @author Administrator**/
public class CorsFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}// @Override// public void doFilter(ServletRequest servletRequest, ServletResponse// servletResponse, FilterChain filterChain)// throws IOException, ServletException {// HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;//// // Access-Control-Allow-Origin就是我们需要设置的域名// // Access-Control-Allow-Headers跨域允许包含的头。// // Access-Control-Allow-Methods是允许的请求方式// httpResponse.addHeader("Access-Control-Allow-Origin", "*");// *,任何域名// httpResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT,// DELETE");// // httpResponse.setHeader("Access-Control-Allow-Headers", "Origin,// // X-Requested-With, Content-Type, Accept");//// // 允许请求头Token// httpResponse.setHeader("Access-Control-Allow-Headers",// "Origin,X-Requested-With, Content-Type, Accept, Token");// HttpServletRequest req = (HttpServletRequest) servletRequest;// System.out.println("Token=" + req.getHeader("Token"));// if("OPTIONS".equals(req.getMethod())) {// return;// }////// filterChain.doFilter(servletRequest, servletResponse);// }@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {HttpServletResponse resp = (HttpServletResponse) servletResponse;HttpServletRequest req = (HttpServletRequest) servletRequest;// Access-Control-Allow-Origin就是我们需要设置的域名// Access-Control-Allow-Headers跨域允许包含的头。// Access-Control-Allow-Methods是允许的请求方式resp.setHeader("Access-Control-Allow-Origin", "*");// *,任何域名resp.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE");// resp.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,// Content-Type, Accept");// 允许客户端,发一个新的请求头jwtresp.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With, Content-Type, Accept, jwt");// 允许客户端,处理一个新的响应头jwtresp.setHeader("Access-Control-Expose-Headers", "jwt");// String sss = resp.getHeader("Access-Control-Expose-Headers");// System.out.println("sss=" + sss);// 允许请求头Token// httpResponse.setHeader("Access-Control-Allow-Headers","Origin,X-Requested-With,// Content-Type, Accept, Token");// System.out.println("Token=" + req.getHeader("Token"));if ("OPTIONS".equals(req.getMethod())) {// axios的ajax会发两次请求,第一次提交方式为:option,直接返回即可return;}filterChain.doFilter(servletRequest, servletResponse);}@Overridepublic void destroy() {}
}
web.xml中配置:

注1:axios跨域问题会一直报错:“http://127.0.0.1:8848' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header”因为使用了前后端分离开发,跨域访问了,解决方案:需要配置tomcat允许跨域访问,tomcat跨域配置方法很多,但最简单的方式是自己写一个过滤器CorsFilter实现,添加一个响应头Access-Control-Allow-Origin即可httpResponse.addHeader("Access-Control-Allow-Origin", "*");//*表示任何域名httpResponse.addHeader("Access-Control-Allow-Origin", "http://localhost:80");Access-Control-Allow-Origin:* #则允许所有域名的脚本访问该资源。Access-Control-Allow-Origin:https://www.fujieace.com #允许特定的域名访问注2:axios.get提交没有问题,axios.post提交后台接收不到数据因为POST提交的参数的格式是Request Payload,这样后台取不到数据的解决方案:使用qs.js库,将{a:'b',c:'d'}转换成'a=b&c=d'注3:为简化axios使用,还可以使用axios全局配置及拦截器,详情见资料“api/http.js”axios.defaults.baseURL = 'https://api.example.com';//axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;//自定义请求头,添加认证令牌axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';注4:为方便开发,建议对请求地址进行封装,详情见资料“api/action.js”注5:^_^~~~~为进一步简化开发,将action.js的URL地址封装到axios.urls属性上
5.axios 的 get/post 的区别( qs )
1.题外话:vue.js有著名的全家桶系列:vue-router,vuex, vue-resource,再加上构建工具vue-cli,就是一个完整的vue项目的核心构成。其中vue-resource是Vue.js的一款插件,它可以通过XMLHttpRequest或JSONP发起请求并处理响应,但在vue更新到2.0之后,作者就宣告不再对vue-resource更新,而是推荐的axios2.GET提交axios.get('/user', {//注意数据是保存到json对象的params属性params: {ID: 12345}}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});3.POST提交axios.post('/user', {//注意数据是直接保存到json对象firstName: 'Fred',lastName: 'Flintstone'}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});


6.This 指针带来的变量污染


我太难了
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
