一、Vue概述
(一)Vue是什么
Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的渐进式框架。Vue 只关注视图层, 采用自底向上增量开发的设计。
Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。
Vue.JS是优秀的前端 JavaScript 框架
(二)为什么学习Vue
随着项目业务场景的复杂,传统模式(html+jquery)已无法满足需求,就出现了Angular/React/Vue等框架
企业需求、主流框架之一、易用、灵活、高效
(三)Vue能做什么
最大程度上解放了 DOM 操作
单页web项目开发
传统网站开发
二、Vue核心特征
① 解耦视图与数据
② M-V-VM模型 关注模型和视图
M:即Model,模型,包括数据和一些基本操作。
V:即View,视图,页面渲染结果
VM:即View-Model,模型和视图间的双向操作
③ 双向数据绑定
(一)MVVM之前
开发人员从后端获取需要的数据模型,然后要通过DOM操作Model渲染到View中。而后当用户操作视图,我们还需要通过DOM获取View中的数据,然后同步到Model中
(二)MVVM之后
而MVVM中的VM要做的事情就是把DOM操作完全封装起来,开发人员不用再关心Model和View之间是如何互相影响的:
- 只要我们Model发生了改变,View上自然就会表现出来。
- 当用户修改了View,Model中的数据也会跟着改变
把开发人员从繁琐的DOM操作中解放出来,把关注点放在如何操作Model上
三、Vue入门
NPM是Node提供的模块管理工具,可以非常方便的下载安装很多前端框架,包括Jquery、AngularJS、VueJs都有。为了后面学习方便,我们先安装node及NPM工具
node.js下载地址:https://nodejs.org/en/download/,安装完成Node应该自带了NPM了,在控制台输入npm -v查看
注:
① 在v12.16.2以上版本就不在支持window7系统。
② npm默认的仓库地址是在国外网站,速度较慢,建议大家设置到淘宝镜像。但是切换镜像是比较麻烦的。推荐一款切换镜像的工具:nrm
安装命令:npm install nrm -g 这里-g代表全局安装
查看npm的仓库列表:nrm ls
指定镜像源:nrm use taobao
测试速度:nrm test npm
(一)下载安装
vue是一个前端框架,也是其实是一个js文件,下载vue.js文件并在页面中引入
vue.js的下载方式:
① 可以引入在线的vue.js(公共的CDN服务)
<!-- 开发环境版本,包含了用帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
或
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
② 可以离线下载vue.js
开发版本: https://vuejs.org/js/vue.js
生产版本: https://vuejs.org/js/vue.min.js
③ npm包资源管理器,可以下载vue.js(推荐)
初始化:npm init -y
安装vue:npm install vue --save
注:切记重启计算机
(二)第一个vue
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>第一个Vue</title><script src="vue.js"></script>
</head>
<body><div id="app"><h2>{{name}}<h2></div> <script type="text/JavaScript"> //1、创建vue对象var app = new Vue({el:"#app",data:{name:"Deam!"}})</script></body>
</html>
Vue参数详解:
1. body中,设置Vue管理的视图<div id="app"></div>
2. 引入vue.js
3. 实例化Vue对象 new Vue();
4. 设置Vue实例的选项:如el、data...
new Vue({选项:值});
5. 在<div id='app'></div>中通过{{ }}使用data中的数据
四、Vue常见指令
指令 (Directives) 是带有 v- 前缀的特殊attribute。是Vue框架提供的语法,扩展了html标签的功能、大部分的指令的值是js的表达式。用于取代DOM操作
(一)v-text 和 v-html
类似innerText和innerHTML
① v-text:更新标签中的内容
② v-html:更新标签中的内容/标签
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>V-Html AND V-Text</title>
</head>
<body><div id="mapp"><h2 V-html="value"></h2><h2 V-text="value"></h2></div><script src="vue.js"></script><script>var mapp = new Vue({el:"#mapp",data:{value:"<i>Deam!</i>"}})</script></body>
</html>
(二)v-if 和 v-show
根据表达式的boolean值进行判断是否渲染该元素
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>V-If AND V-Show</title><script src="vue.js"></script>
</head>
<body><!-- v-if 和v-show的区别:v-if:真正意义的渲染,根据条件进行组件的销毁和重组v-show:不管条件是什么,都会进行渲染,只是根据值进行css的切换--><div id="mapp"><p v-if="b">显示吗?</p><p v-show="b">显示</p><p v-if="c">显示吗?</p><p v-show="c">显示</p></div><script>new Vue({el:"#mapp",data:{b:true,c:false}})</script></body>
</html>
(三)v-on
① 作用:使用 v-on 指令绑定 DOM 事件,并在事件被触发时执行一些 JavaScript 代码。
② 语法:
v-on:事件名.修饰符 = "methods中的方法名";
v-on的简写方法: @事件名.修饰符 = "methods中的方法名";
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>V-on</title><script src="vue.js"></script>
</head>
<body><div id="mapp"><h2>{{num}}</h2><h2><button v-on:click="num++">加加</button><br><button @click="clickFunction()">点我</button> <br><button @click="clickFunctions(num)">继续点我</button> <br><button @click="clickFunction">再加加</button> <br><input type="text" @change="changeFunction()"></h2></div><script>new Vue({el:"#mapp",data:{num:0},methods:{clickFunction:function(){console.log("点我干什么?")},clickFunctions:function(num){console.log("点我干什么?")console.log(num)},changeFunction:function(){console.log("内容改变!")}}})</script></body>
</html>
(四)v-for
① 作用:列表渲染,当遇到相似的标签结构时,就用v-for去渲染
② 格式:
【1】(item,index) in 数组或集合
参数item:数组中的每个元素
参数index:数组中元素的下标
【2】(value, key, index) in 对象
参数index:对象中每对key-value的索引 从0开始
参数key:键
参数value:值
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>V-for</title><script src="vue.js"></script>
</head>
<body><div id="mapp"><!-- 遍历数组 --><table border="1" cellspacing="0" align="center"><tr v-for="(item,index) in students"><td>{{index}}</td><td>{{item.id}}</td><td>{{item.name}}</td><td>{{item.age}}</td><td>{{item.功夫}}</td></tr></table><!-- 遍历对象 --><form align="center"><p v-for="(value, key, index) in user"><label>{{key}}</label>:<input type="text" v-model="value"></p></form></div><script>new Vue({el:"#mapp",data:{students:[{id:"1001",name:"令狐冲",age:32,功夫:"吸星大法、独孤九剑"},{id:"1002",name:"欧阳锋",age:58, 功夫:"蛤蟆功、灵蛇拳"},{id:"1003",name:"杨过",age:28, 功夫:"黯然销魂掌、玄铁剑法"},{id:"1004",name:"郭靖",age:35, 功夫:"降龙十八掌、九阴真经"},{id:"1005",name:"张无忌",age:25, 功夫:"九阳神功、乾坤大挪移"},{id:"1006",name:"段誉",age:22, 功夫:"六脉神剑、凌波微步"},{id:"1007",name:"虚竹",age:27, 功夫:"天山六阳掌、生死符"},{id:"1008",name:"乔峰",age:33, 功夫:"降龙十八掌、擒龙功"},{id:"1009",name:"小龙女",age:24, 功夫:"玉女心经、左右互搏术"},{id:"1010",name:"周伯通",age:60, 功夫:"空明拳、双手互搏"},{id:"1011",name:"黄药师",age:55, 功夫:"弹指神通、落英神剑掌"},{id:"1012",name:"欧阳锋",age:58, 功夫:"蛤蟆功、灵蛇拳"}],user:{id:"0000",name:"岳不群",age:"60"}}})</script>
</body>
</html>
(五)v-bind
① 作用: 可以绑定标签上的任何属性
② 格式:v-bind:属性="值"
③ 简写格式::属性="值"
④ 属性值一部分进行替换的格式::属性="'常量值' + vue对象data中的数据"
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>V-bind</title><script src="vue.js"></script>
</head>
<body><div id="mapp"><font v-bind:color="b">Its Beaning a long day.</font><font :color="r">Without you my friend.</font><a :href="'https://'+baidu">Deam!</a></div><script>new Vue({el:"#mapp",data:{b:"blue",r:"red",baidu:"www.baidu.com"}})</script></body>
</html>
(六)v-model
① 作用:表单元素的绑定
② 特点:双向数据绑定
(1)vue对象中的数据发生变化可以更新到界面
(2)通过界面可以更改vue对象中数据
(3)v-model 会忽略所有表单元素的 value、 checked 、 selected 特性的初始值而总是将 Vue 实 例的数据作为数据来源。应该在data选项中声明初始值。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>V-model数据的双向绑定</title><script src="vue.js"></script>
</head>
<body><div id="mapp"><form>用户名:<input type="text" :value="name">{{name}}用户名:<input type="text" V-model:value="name">{{name}}<input type="button" @click="update" value="修改"></form><script>new Vue({el:"#mapp",data:{name:"徐超一"},methods:{update:function(){this.name="孙莲奔"}}})</script>
</body>
</html>
(七)计算属性
在插值表达式中使用js表达式是非常方便的,而且也经常被用到。
但是如果表达式的内容很长,就会显得不够优雅,而且后期维护起来也不方便
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>计算属性</title><script src="vue.js"></script>
</head>
<body><div id="mapp"><h2>原始BirthDay:<span>{{birthday}}</span><br>没有使用计算属性的BirthDay:<span>{{new Date(birthday).getFullYear()+'-'+new Date(birthday).getMonth()+1+'-'+new Date(birthday).getDate()}}</span><br>使用计算属性的BirthDay:<span>{{getBirthday}}</span></h2></div><script>new Vue({el:"#mapp",data:{birthday:1610669793429},computed:{getBirthday(){return new Date(this.birthday).getFullYear()+'-'+new Date(this.birthday).getMonth()+1+'-'+new Date(this.birthday).getDate()}}})</script></body>
</html>
(八)watch
watch可以让我们监控一个值的变化。从而做出相应的反应。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>watch</title><script src="vue.js"></script><!-- watch可以让我们监控一个值的变化。从而做出相应的反应。 -->
</head>
<body><div id="mapp"><input type="text" v-model="hello"></div><script>new Vue({el:"#mapp",data:{hello:"hello"},watch:{hello(newValue,oldValue){console.log(newValue,oldValue)}}})</script></body>
</html>
五、Vue的生命周期
每个 Vue 实例在被创建时都要经过一系列的初始化过程 :创建实例,装载模板,渲染模板等等。Vue为生命周期中的每个状态都设置了钩子函数(监听函数)。每当Vue实例处于不同的生命周期时,对应的函数就会被触发调用。
Vue的生命周期
(一)理解
每个 Vue 实例在被创建时都要经过一系列的初始化过程 :创建实例,装载模板,渲染模板等等。 Vue
为生命周期中的每个状态都设置了钩子函数(监听函数)。每当 Vue 实例处于不同的生命周期时,对应的函数 就会被触发调用。
(二)钩子函数
1 、创建时的四个事件
beforeCreate :实例被创建之前执行
created : created 执行时, data 和 methods 都已经被初始化好了!
beforeMount : beforeMount 执行时,模板已经在内存中编辑完成了,尚未被渲染到页面中
mounted :内存中的模板已经渲染到页面,用户已经可以看见内容
2 、运行中的两个事件
beforeUpdate : beforeUpdate 执行时,内存中的数据已更新,但是页面尚未渲染
updated : updated 执行时,内存中的数据已更新,并且页面已经被渲染
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vue的生命周期</title><script src="vue.js"></script>
</head>
<body><div id="mapp"> <p>{{message}}</p></div><script>new Vue({el:"#mapp",data:{message:""},beforeCreated(){this.message="创建之前"},created(){this.message="创建之后"}})</script></body>
</html>
六、组件
(一)介绍
组件( Component )是 Vue.js 最强大的功能之一。
(二)作用
1 、组件可以扩展 HTML 元素,封装可重用的代码。
2 、组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树 。
(三)组件的定义
全局组件的特点:
1 、组件其实也是一个 Vue 实例,因此它在定义时也会接收: data 、 methods 、生命周期函数等。
2 、不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有 el 属性。
3 、组件渲染需要 html 模板,所以增加了 template 属性,值就是 HTML 模板。
4 、全局组件定义完毕,任何 vue 实例都可以直接在 HTML 中通过组件名称来使用组件了。
5 、 data 的定义方式比较特殊,必须是一个函数。
注:定义组件要在 Vue 对象之前声明 -->
(四)定义全局组件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>全局组件</title><script src="vue.js"></script>
</head>
<body><div id="mapp"><btn></btn></div><script>//定义全局组件 参数1:组件名 参数2:组件参数Vue.component("btn",{template:"<button @click='count++'>加加</botton>{{count}}",data(){return{count:0}}})new Vue ({el:"#mapp"})</script>
</body>
</html>
特点:
- 组件其实也是一个Vue实例,因此它在定义时也会接收:data、methods、生命周期函数等
- 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
- 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板
- 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了。
- data的定义方式比较特殊,必须是一个函数。
注:定义组件要在Vue对象之前声明
(五)定义局部组件
一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着Vue的加载而加载。因此,对于一些并不频繁使用的组件,我们会采用局部注册。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>局部组件</title><!--
局部组件的特点:1 、一旦全局注册,就意味着即便以后你不再使用这个组件,它依然会随着 Vue 的加载而加载。2 、对于一些并不频繁使用的组件,我们会采用局部注册。4 、 components 就是当前 vue 对象子组件集合。其 key 就是子组件名称,其值就是组件对象的属性5 、效果与刚才的全局注册是类似的,不同的是,这个 conn 组件只能在当前的 Vue 实例中使用注:定义组件要在 Vue 对象之前声明 --><script src="vue.js"></script><style>button {font-size: 20px;width: 150px;height: 50px;display: block;margin: 20px auto;}</style>
</head>
<body><div id="mapp"><conn></conn> </div><script>//声明局部变量const conn={template:"<button @click='count++'>{{count}}</button>",data(){return{count:1}}}new Vue({el:"#mapp",components:{conn:conn //注册局部变量}})</script></body>
</html>
- components就是当前vue对象子组件集合。
- 其key就是子组件名称
- 其值就是组件对象的属性
- 效果与刚才的全局注册是类似的,不同的是,这个conn组件只能在当前的Vue实例中使用
注:定义组件要在Vue对象之前声明
(六)组件通信
通常一个单页应用会以一棵嵌套的组件树的形式来组织,如下:
- 页面首先分成了顶部导航、左侧内容区、右侧边栏三部分
- 左侧内容区又分为上下两个组件
- 右侧边栏中又包含了3个子组件
各个组件之间以嵌套的关系组合在一起,那么这个时候不可避免的会有组件间通信的需求。
① 父向子传递
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>组件通信之父传子</title><script src="vue.js"></script>
</head>
<body><div id="mapp"><par content="Hello h2"></par></div><script>Vue.component("par",{template:"<h2>{{content}}</h2>",props:["content"] //可以作为一个标签的属性进行赋值操作})new Vue({el:"#mapp"})</script></body>
</html>
② 传递复杂数据
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>传递复杂数据</title><script src="vue.js"></script>
</head>
<body><div id="mapp"><my-list :items="lessons"></my-list></div><script>const myList={template:"<ul><li v-for='item in items':key='item,id'>{{item.id}}:{{item.name}} </li></ul>",props:{items:{type:Array,default:[]}}}new Vue({el:"#mapp",components:{myList:myList},data:{lessons:[{id:"1001",name:"莎莎"},{id:"1002",name:"乖乖"},{id:"1003",name:"东新"}]}})</script></body>
</html>
注:单页面中父组件和子组件的使用 自定义标签时的问题。如 <my-list></my-list> 与 <my-list />
③ 子向父传递
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>子组件从父组件传递信息</title><script src="vue.js"></script>
</head><body><div id="mapp"><h2>{{num}}</h2><!-- 引入了名为 btn 的自定义组件,并通过 v-bind(缩写为 :)将父组件中的 num 属性传递给子组件。 --><btn :num="num"></btn> <!-- 报错:Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "num" --></div><script>Vue.component("btn",{template:"<div><button @click='num++'>{{num}}</button><br><button @click='num--'>{{num}}</button></div>",props:['num'] //设置一个属性})new Vue({el:"#mapp",data:{num:0}})</script></body>
</html>
报错:[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "num"
原因:子组件接收到父组件属性后,默认是不允许修改的
解决:既然只有父组件能修改,那么加1和减1的操作一定是放在父组件
var app = new Vue({
el:"#app",
data:{
num:0
},
methods:{ // 父组件中定义操作num的方法
(){
this.num++;
},
decrement(){
this.num--;
}
}
})
点击按钮是在子组件中,那就是说需要子组件来调用父组件的函数,可以通过v-on指令将父组件的函数绑定到子组件上
<div id="app">
<h2>num: {{num}}</h2>
<btn :num="num" @incre="increment" @decre="decrement"></btn>
</div>
当子组件中按钮被点击时,调用绑定的函数
Vue.component("btn",{
template:"<div><button @click='plus'>加1</button> <button @click='reduce'>减1</button></div>",
props:['num'],
methods:{
plus(){
this.$emit("incre");
},
reduce(){
this.$emit("decre");
}
}
})
注:vue提供了一个内置的this.$emit函数,用来调用父组件绑定的函数
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>解决报错</title><script src="vue.js"></script>
</head>
<body><div id="mapp"><h2>{{num}}</h2><!-- 引入了名为 btn 的自定义组件,并通过 v-bind(缩写为 :)将父组件中的 num 属性传递给子组件。 --><btn :num="num" @incre="increment" @decre="decrement"></btn> </div><script>Vue.component("btn",{template:"<div><button @click='plus'>加加</button><button @click='reduce'>减减</button></div>",props:['num'], //设置一个属性nummethods:{plus(){this.$emit("incre"); //使用Vue的内置函数,获取父组件的信息},reduce(){this.$emit("decre");}}})new Vue({el:"#mapp",data:{num:0},methods:{increment(){this.num++},decrement(){this.num--}}})</script></body>
</html>
七、Vue的Ajax(axios)
在Vue.js中发送网络请求本质还是ajax,我们可以使用插件方便操作。
1. vue-resource: Vue.js的插件,已经不维护,不推荐使用
2. axios :不是vue的插件,可以在任何地方使用,推荐
3. 通过Http请求的不同类型(POST/DELETE/PUT/GET)来判断是什么业务操作(CRUD ) HTTP方法规则举例
说明:
① POST Create 新增一个没有id的资源
② GET Read 取得一个资源
③ PUT Update 更新一个资源。或新增一个含 id 资源(如果 id 不存在)
④ DELETE Delete 删除一个资源
(一)安装
方式1:使用npm安装
命令:npm install axios
我们直接导入对应的本地依赖就行
方式2:使用cdn链接axios
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
(二)axios请求
axios({// 请求方式method: 'post',url: 'api',// 传递参数data: obj,// 设置请求头信息headers: {key: value},responseType: 'json'
}).then(response => {// 请求成功let res = response.data;console.log(res);
}).catch(error => {// 请求失败,console.log(error);
});
(三)GET请求
axios.get('/user?id=12345').then(response => {console.log(response.data);}).catch(error => {console.dir(error)
});
(四)POST请求
axios.post('/user', "name=迪丽热巴&age=23") .then(response => {console.log(response.data);}).catch(error => {console.dir(err)
});
补充:
为方便起见,为所有支持的请求方法提供了别名
axios.request(confifig)axios.get(url[, confifig])axios.delete(url[, confifig])axios.head(url[, confifig])axios.post(url[, data[, confifig]])axios.put(url[, data[, confifig]])axios.patch(url[, data[, confifig]])
(五)跨域问题
什么是跨域?
指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
什么是同源策略?
是指协议,域名,端口都要相同,其中有一个不同都会产生跨域,在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
跨域问题怎么出现的?
开发一些前后端分离的项目,比如使用 Servlet + Vue 开发时,后台代码在一台服务器上启动,前台代码在另外一台电脑上启动,此时就会出现问题。
比如:
后台 地址为 http://192.168.70.77:8081
前台 地址为 http://192.168.70.88:8080
此时 ip 与 端口号不一致, 不符合同源策略,造成跨域问题。
如何解决:
方式1:后台解决(自定义过滤器)
package com.jn.fliter;import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;@WebFilter("/*")
public class MyFliter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {Filter.super.init(filterConfig);}@Overridepublic void destroy() {Filter.super.destroy();}@Overridepublic void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {HttpServletResponse response = (HttpServletResponse) resp;HttpServletRequest request = (HttpServletRequest) req;// 不使用*,自动适配跨域域名,避免携带Cookie时失效String origin = request.getHeader("Origin");response.setHeader("Access-Control-Allow-Origin", origin);// 自适应所有自定义头String headers = request.getHeader("Access-Control-Request-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(req, resp);}
}
(六)案例
在idea里面新建一个web项目,过滤器使用上诉代码
后台Servlet
package com.jn.servlet;import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.io.PrintWriter;@WebServlet("/axiosTest")
public class AxiosServlet extends HttpServlet {@Override//用于测试axios的前端访问以及get请求访问protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1、获取请求参数String name = req.getParameter("name");String age = req.getParameter("age");System.out.println(name + "\t" + age);//2、响应数据String json = "{\"name\":\"张无忌\",\"age\":\"18\"}";PrintWriter writer = resp.getWriter();writer.print(json);}@Override//用于axios的post请求访问protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//1、获取请求参数String name = req.getParameter("name");String age = req.getParameter("age");//2、响应数据String json = "{\"name\":\"赵敏\",\"age\":\"17\"}";PrintWriter writer = resp.getWriter();writer.print(json);}
}
前台代码:
axios的请求方式
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vue的axios请求</title><script src="vue.js"></script><script src="axios.min.js"></script>
</head>
<body><div id="mapp"><button @click="getdata">点击获取数据</button></div><script>new Vue({el:"#mapp",methods:{getdata(){//方式一:发送axiox请求axios({method:"GET", //请求方式url:"http://localhost:8080/AxiosProject_war_exploded/axiosTest",data:"", //携带参数responseType:"json"}).then(response=>{ //发送成功let rel = response.dataconsole.log(rel)}).catch(error =>{ //发送失败console.log(error)})}}})</script></body>
</html>
然后启动tomcat进行测试
注:别忘了配置跨域过滤器哦
get请求方式
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vue的axios请求</title><script src="vue.js"></script><script src="axios.min.js"></script>
</head>
<body><div id="mapp"><button @click="getdata">点击获取数据</button></div><script>new Vue({el:"#mapp",methods:{getdata(){//方式二:发送axioxGet请求axios.get("http://localhost:8080/AxiosProject_war_exploded/axiosTest",{}).then(response=>{ //发送成功let rel = response.dataconsole.log(rel)}).catch(error =>{ //发送失败console.log(error)})}}})</script></body>
</html>
post请求方式
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vue的axios请求</title><script src="vue.js"></script><script src="axios.min.js"></script>
</head>
<body><div id="mapp"><button @click="getdata">点击获取数据</button></div><script>new Vue({el:"#mapp",methods:{getdata(){//方式二:发送axioxGet请求axios.post("http://localhost:8080/AxiosProject_war_exploded/axiosTest","name=xx&&age=xx").then(response=>{ //发送成功let rel = response.dataconsole.log(rel)}).catch(error =>{ //发送失败console.log(error)})}}})</script></body>
</html>