今日内容
- 组件通信
- Axios
一、组件通信
1、父组件向子组件传值
当组件中需要的数据不是自己定义的,而是通过Vue实例(父组件)传递过来的值时,就需要用到父组件向子组件传值。
实现步骤:
1)子组件使用props属性接收父组件参数。
2)props可以接收多个参数,可以使用数组[“a”,”b”,”c”]。
3)父组件传递给子组件的参数,默认不允许修改,否则会发生vue警告。
2、子组件向父组件传值
可以理解为默认情况下,子组件不能对父组件传递的参数进行修改,那么如果需要在子组件中修改父组件的值时,就需要用到子组件向父组件传值。
说明:
- 子组件接收到父组件属性后,默认是不允许修改的
- 父组件参数只能在父组件方法中修改
- 点击按钮是在子组件中,那就是说需要子组件来调用父组件的函数,可以通过v-on指令将父组件的函数绑定到子组件上
- 当子组件中按钮被点击时,调用绑定的函数,通过内置的this.$emit()函数,来调用父组件绑定的函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="js/vue.min.js"></script> </head> <body> <div id="app"> <calc :num="count" @reduce="reducecount" @add="addcount"></calc> </div> <script> //定义全局组件 Vue.component("calc",{ props:["num"], template:"<div><button @click='reducenum()'>-</button><span>{{num}}</span><button @click='addnum()'>+</button></div>", methods:{ //减 reducenum(){ this.$emit("reduce"); }, //加 addnum(){ this.$emit("add"); } } }) //父组件(Vue实例) var app = new Vue({ el:"#app", data:{ count:0 }, methods:{ //减 reducecount(){ this.count--; }, //加 addcount(){ this.count++; } } }) </script> </body> </html> |
二、Vue的Ajax(Axios)
1、下载安装
概述:
在Vue.js中发送网络请求本质还是Ajax,我们可以使用插件方便操作。
1. vue-resource: Vue.js的插件,已经不维护,不推荐使用
2. axios :不是vue的插件,可以在任何地方使用,推荐
引入方式有两种:
- CDN在线导入:<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
- 下载后本地导入:<script src="js/axios.min.js"></script>
2、Axios语法
A.完整模板:
$.ajax({
})
axios({
method: 'post', // 请求方式 type
url: 'api', //后台地址
data: obj, // 传递参数,这里必须使用URLSearchParams类型参数
headers: { // 设置请求头信息,后面做上传时使用
key: value
},
responseType: 'json' //响应数据类型 dataType
}).then(response => { //请求成功
let res = response.data;//获取响应数据
console.log(res);
}).catch(error => { //请求失败
console.log(error);
});
- get请求模板
axios.get('url?id=12345').then(response => {
console.log(response.data);
}).catch(error => {
console.log(error)
});
- post请求模板
axios.post('url', "name=迪丽热巴&age=23").then(response => {
console.log(response.data);
}).catch(error => {
console.log(err)
});
3、跨域处理
1)跨域概念
什么是跨域?
指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
什么是同源策略?
是指协议(http),域名(baidu),端口(8080)都要相同,其中有一个不同都会产生跨域,在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
跨域问题怎么出现的?
开发一些前后端分离的项目,比如使用 Servlet + Vue 开发时,后台代码在一台服务器上启动,前台代码在另外一台电脑上启动,此时就会出现问题。
比如:
后台 地址为 http://192.168.70.77:8081
前台 地址为 http://192.168.70.88:8080
此时 ip 与 端口号不一致,不符合同源策略,造成跨域问题。
2)解决跨域
自定义过滤器,核心代码:
/*
跨域请求处理
*/
@WebFilter("/*")
public class CrossFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
//设置post请求中文乱码
request.setCharacterEncoding("utf-8");
//返回中文乱码处理
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
// 不使用*,自动适配跨域域名,避免携带Cookie时失效
String origin = request.getHeader("Origin");
if(StringUtils.isNotBlank(origin)) {
response.setHeader("Access-Control-Allow-Origin", origin);
}
// 自适应所有自定义头
String headers = request.getHeader("Access-Control-Request-Headers");
if(StringUtils.isNotBlank(headers)) {
response.setHeader("Access-Control-Allow-Headers", headers);
response.setHeader("Access-Control-Expose-Headers", headers);
}
// 允许跨域的请求方法类型
response.setHeader("Access-Control-Allow-Methods", "*");
// 预检命令(OPTIONS)缓存时间,单位:秒
response.setHeader("Access-Control-Max-Age", "3600");
// 明确许可客户端发送Cookie,不允许删除字段即可
response.setHeader("Access-Control-Allow-Credentials", "true");
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
- 处理浏览器跨域不携带Cookie的问题
在chrome浏览器地址栏输入chrome://flags并回车
在搜索栏中输入SameSite by default cookies搜索,并禁用如图中的两项设置,改为Disabled即可点击右下键ReLaunch重启浏览器即可
如果是火狐浏览器不需要处理。
- VUE+Axios案例
图书信息的CRUD:
前端页面代码
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>图书列表页面</title> <style> tr{ text-align: center; } </style> <script src="js/vue.min.js"></script> <script src="js/axios.min.js"></script> </head> <body> <div id="app"> <table border="1px" width="800px" align="center" cellspacing="0" cellpadding="5"> <caption> <h2>图书列表展示</h2> <p><a href="addbook.html">添加新图书</a></p> </caption> <tr> <th>图书编号</th> <th>图书名称</th> <th>图书价格</th> <th>图书作者</th> <th>图书简介</th> <th>操作</th> </tr> <tr v-for="(book,index) in list"> <td>{{book.bid}}</td> <td>{{book.bname}}</td> <td>{{book.bprice}}</td> <td>{{book.bauthor}}</td> <td>{{book.bdesc}}</td> <td> <a href="javascript:void(0)" @click="updateBook(book.bid)">修改</a> <a href="javascript:void(0)" @click="delBook(book.bid)">删除</a> </td> </tr> </table> </div> <!-- js代码开始 --> <script> var app = new Vue({ el:"#app", data:{ list:[] //保存查询的集合数据 }, created(){ this.findAllBook(); }, methods:{ findAllBook(){ axios({ method:"get", url:"http://localhost:8080/booksys/book?method=findAllBook" }).then(resp => { this.list = resp.data.data; }).catch(resp => { console.log(resp); }) }, updateBook(bid){ location.href = "updatebook.html?bid="+bid; }, delBook(bid){ if(confirm("确定要删除吗?")){ axios.get("http://localhost:8080/booksys/book?method=delBook&bid="+bid).then(resp=>{ location.href = "index.html"; }).catch(resp =>{ console.log(resp); }) } } } }) </script> </body> </html> |
addbook.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>添加图书</title> <script src="js/vue.min.js"></script> <script src="js/axios.min.js"></script> </head> <body> <div id="app"> <form id="login" action="" method="POST"> <table border="1px" cellpadding="10px" cellspacing="0" align="center" width="500px"> <caption><h2>添加新图书</h2></caption> <tr> <td>书名</td> <td> <input type="text" v-model="book.bname"> </td> </tr> <tr> <td>价格</td> <td> <input type="text" v-model="book.bprice"> </td> </tr> <tr> <td>作者</td> <td> <input type="text" v-model="book.bauthor"> </td> </tr> <tr> <td>简介</td> <td> <textarea rows="4" cols="40" v-model="book.bdesc"></textarea> </td> </tr> <tr align="center"> <td colspan="2"> <input type="button" value="添加" @click="addBook"> <input type="reset" value="取消"> </td> </tr> </table> </form> </div> <!-- js代码开始 --> <script> var app = new Vue({ el:"#app", data:{ book:{ bname:'', bprice:'', bauthor:'', bdesc:'' } }, methods:{ addBook(){ //封装表单数据 var params = new URLSearchParams(); params.append("bname",this.book.bname); params.append("bprice",this.book.bprice); params.append("bauthor",this.book.bauthor); params.append("bdesc",this.book.bdesc); //请求后台 axios({ method:"post", url:"http://localhost:8080/booksys/book?method=addBook", data:params }).then(resp => { console.log(resp.data); alert(resp.data.msg); //返回列表页面 location.href = "http://127.0.0.1:5500/book_front/index.html"; }).catch(resp => { console.log(resp); }) } } }) </script> </body> </html> |
updatebook.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>修改图书</title> <script src="js/vue.min.js"></script> <script src="js/axios.min.js"></script> </head> <body> <div id="app"> <form> <table border="1px" cellpadding="10px" cellspacing="0" align="center" width="500px"> <caption><h2>修改图书信息</h2></caption> <tr> <td>书名</td> <td> <input type="hidden" v-model="book.bid"> <input type="text" v-model="book.bname"> </td> </tr> <tr> <td>价格</td> <td> <input type="text" v-model="book.bprice"> </td> </tr> <tr> <td>作者</td> <td> <input type="text" v-model="book.bauthor"> </td> </tr> <tr> <td>简介</td> <td> <textarea v-model="book.bdesc" rows="4" cols="40"></textarea> </td> </tr> <tr align="center"> <td colspan="2"> <input type="button" value="修改" @click="updateBook()"> <input type="button" value="返回" @click="back()"> </td> </tr> </table> </form> </div> <script> var app = new Vue({ el:"#app", data:{ book:{ bid:'', bname:'', bprice:'', bauthor:'', bdesc:'' } }, created(){ this.showBook(); }, methods:{ showBook(){ //获取url中的bid var url = window.location.href; var bid = url.substring(url.trim().lastIndexOf("=")+1); /* let params = new URLSearchParams(); params.append("bid",bid); params.append("method","showBookByBid"); */ axios({ method:"get", url:"http://localhost:8080/booksys/book?method=showBookByBid&bid="+bid, }).then(resp => { console.log(resp.data.data); this.book = resp.data.data; }).catch(resp =>{ console.log(resp); }) }, updateBook(){ //封装表单数据 var params = new URLSearchParams(); params.append("bname",this.book.bname); params.append("bprice",this.book.bprice); params.append("bauthor",this.book.bauthor); params.append("bdesc",this.book.bdesc); params.append("bid",this.book.bid); params.append("method","updateBook"); axios({ method:"post", data:params, url:"http://localhost:8080/booksys/book" }).then(resp =>{ alert(resp.data.msg); location.href = "index.html"; }).catch(resp =>{ console.log(resp); }) }, back(){ history.back(); } } }) </script> </body> </html> |
后台代码
- 使用分层模式搭建项目
- 添加跨域处理过滤器
- 创建统一返回处理类ResultVo
ResultVo
package com.offcn.utils; |
Servlet代码
package com.offcn.servlet; |
底层代码省略。