赞
踩
B站 博哥视屏
基本创建方式
List<String> list = Arrays.asList("A","B","C","D"); list.stream().foreEach(s->System.out.println(s)); list.forEach(System.out::println); List<String> list = Arrays.asList(3,4,5,6); list.stream().filter(s -> s%2 == 0).collect(Collectors.tolist()); //取出所有偶数 List<Person> list = Arrays.aslist(new Person(34,"张三"),new Person(56,"李四")); Set<Person> people = new TreeSet<>((01, o2) -> o1.getId() - o2. getId()); //通过id来进行升序排序 System.out.print1n(peop1e); List<Integer> list = Arrays.aslist(3, 4, 5, 6); //求和 System . out. println(list. stream(). reduce(日, (prev, val) -> prev += val). intValue()); List<String> list = Arrays.asList("A", "B", "C"); // 拼接成 A,B,C 模式 System. out . println(list. stream().reduce("",(prev, val) -> prev += val + ","));
VUE开发环境推荐使用VS code, 然后安装特定的插件即可开发,可用插件如下:
var 关键字存在的问题,
1.var声明的变量可以重复声明,
2.var的作用域不明显,循环外面可以取到循环里面的值
1.let和const关键字
let 声明变量 let a = 3
const 声明常量(常量不能重复声明) const a = 56
2.对象的高级定义
<script> const age = 10 const name = '张三' const person = {age,name} //等同于 const person = {age: age,name: name} </script>
- 1
- 2
- 3
- 4
- 5
3.箭头函数(箭头函数中没有this,this取值是代码书写时上下文的值)
<script> //弹幕,2秒运行一次 setInterval(funcation(){ console.log("=======") },2000) const arr = [3,4,5,6] arr.forEach((item,idx) => { console.log(item,idx) }) //等同于 // const arr = [3,4,5,6] // arr.forEach(function(item,idx){ // console.log(item,idx) // }) const arr = [31,45,5,6] arr.sort((v1,v2)=>v1 - v2) //排序 console.log(arr) </script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
4.解构赋值
<script> let person = {age: 10,name: '张三',address: '北京'} // let age = person.age // let name = person.name // let address = person.address let {age,name,address} = person console.log(age,name,address) </script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
5.扩展运算符
<script> let arr = [3,4,5] //concat() 将参数中的数组填充到调用的数组中 // let arr1 = [6,7].concat(arr) // console.log(arr1) let arr1 = [6,7,...arr] let o1 = {name: 'zs',age:1} let o2 = {address: '北京',...o1} console.log(o2) </script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
6.js数组的高级用法
<script> let arr = [5,67,90,20,34,46] //过滤出所有的偶数 let arr1 = arr.filter(val => val % 2 === 0) //找到第一个偶数所在的索引位置 let arr2 = arr.findIndex(val => val % 2 === 0) //找到第一个偶数并将其删除 let arr3 = arr.splice(arr.findIndex(val = > val % 2 === 0),1) //找到第一个偶数并将其删除,并在该位置插入,100,200 let arr4 = arr.splice(arr.findIndex(val = > val % 2 === 0),1,100,200) //找到满足条件的第一个数据 let arr5 = arr.find(val = > val % 2 === 0) //map,将一个数组转换成另一个数组 //将数组的元素平方 let arr6 = arr.map(val => val * val) //使数组输出时每个元素之间加上,号 let arr7 = arr.join(",") //reduce()函数 let arr = [1,2,3,4,5] //求和 console.log(arr.reduce((a,b) => a + b))//15 //求乘积 console.log(arr.reduce((a,b) => a * b))//120 </script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
7.模板字符串
<script> content.innerHTML = users.map(u =>`<tr><td>${u.id}</td><td>${u.name}</td><td>${u.address}</td></tr>`).join('') </script>
- 1
- 2
- 3
8.ajax的回调地狱问题
下一次网络请求的结果 需要依赖上一次请求的结果
.then
9.ES6 的模块化
libs/util.js
function add(a,b){ return a + b} function multiply(a,b){ return a * b} //表示对外暴露一个方法 export{ add, multiply } //这里add 等同于 add:add
- 1
- 2
- 3
- 4
<!-- js模块的时候,type必须是 module--> <script type="module"> <!--util.js是通过 export方式对外暴露的,所以必须通过解构的方式来import--> import{ add,multiply} from './libs/util.js' console.log(add(3,4)); //7 </script>
- 1
- 2
- 3
- 4
- 5
- 6
10.ES6 的 默认 模块化
libs/other.js
function add(a,b){ return a + b} function multiply(a,b){ return a * b} //全文只能有一个export default export default{ add, multiply } //这里add 等同于 add:add
- 1
- 2
- 3
- 4
<script type="module"> <!--other.js是通过 export default方式对外暴露的,只能通过对象的方式来import--> import ot from './libs/util.js' console.log(ot.add(3,4)); //7 </script>
- 1
- 2
- 3
- 4
- 5
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<div id="app">
{{msg}}
</div>
new Vue({
el: "#app",
data() {
return {
msg: "Hello World"
}
}
});
v-text: v-text是用于操作纯文本,它会替代显示对应的数据对象上的值,可以简写为{{}}, 即插值表达式。
v-html: 将内容以html的形式呈现在页面。
v-if: 值如果为true的情况下,显示标签,如果为false会移除标签。
v-else-if: 与v-if配合使用。
v-else: 与v-if配合使用。
v-show: 如果为true,显示信息,如果为false则隐藏标签。
v-for: 循环遍历。语法形式为 v-for=“item in list”
v-bind: 将值绑定到标签的自定义属性上,形式为 v-bind:title=“mytitle”,可以简写为 :属性名
v-model: 双向数据绑定。
v-on:click: 点击事件,可以简写为@click。
如下代码为v-bind的演示:
<head> <style> .cls{ color: red; } .cls1{ font-size: 30px; } .cls2{ line-height: 40px; } </style> </head> <body> <div id="app"> <p v-bind:class="{cls:isCls}">这是一段话</p> <p :class="[one, two, {cls:isCls}]">这是一段话</p> <p :title="attr">这是一段话</p> </div> </body> <script> new Vue({ el: "#app", data: { isCls: true, content: 'hello world', one: 'cls1', two: 'cls2', attr: '附加属性' } }); </script>
案例:1. 通过表单添加数据,渲染到列表中。
2. 遍历数组和对象,并能删除和更新。
一个盒子中嵌套另外一个盒子的时候,在内外层的盒子中都有有对应的事件行为,当点击内层盒子时候,默认情况下会触发外层盒子的事件,这种默认的行为就是事件冒泡。需要去阻止事件的冒泡。使用方法:
@click.stop="方法名"
对于form表单来说,当点击表单中的button的时候,会默认触发表单的提交;对于a标签,当点击a标签的时候,会触发a标签访问。那么如何去阻止a标签的默认访问行为呢,使用方法是:
@click.prevent="方法名"
<input @keyup.13="showInfo" v-model="info"><br>
<input @keyup.enter="showInfo" v-model="info"><br>
new Vue({
el: '#app',
data: {
info: ''
},
methods: {
showInfo(){
alert(this.info);
}
}
})
所谓的监视器就是可以通过watch的方式观察某个属性的变化,然后做出相应的处理。
<div id ="app"> <input type="text" v-model="msg"> <input type="text" v-model="stu.name"> </div> <script> //创建Vue实例,得到 ViewModel var vm = new Vue({ el: '#app', data:{ msg:"", stu:{ name:"", } }, methods: {}, watch: { msg(newVal,oldVal){ console.log(newVal); console.log(oldVal); }, "stu.name":{ handler(newVal,oldVal){ console.log(oldVal+"--->"+newVal); } } }, }); </script>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="./lib/vue.js"></script> <script src="./lib/city.js"></script> </head> <body> <div id ="app"> <select v-model:id="provinceId"> <option value="-1">请选择省份</option> <option :value="item.id" v-for="(item, index) in provinceAll" :key="index">{{item.name}}</option> </select> <select v-model:id="cityId"> <option value="-1">请选择城市</option> <option :value="item.id" v-for="(item, index) in cityAll" :key="index">{{item.name}}</option> </select> <select v-model:id="districtId"> <option value="-1">请选择区</option> <option :value="item.id" v-for="(item, index) in districtAll" :key="index">{{item.name}}</option> </select> </div> <script> //创建Vue实例,得到 ViewModel var vm = new Vue({ el: '#app', data:{ provinceAll:province, provinceId:-1, cityAll:[], cityId:-1, districtAll:[], districtId:-1, }, methods: {}, watch: { provinceId(newVal,oldVal){ //恢复默认 this.cityId=-1; // 清空数组 this.cityAll=[]; //循环通过省份id查询所有符合的城市,放到数组里 city.forEach(city=> { if(city.upid==newVal){ this.cityAll.push(city) } }); }, cityId(newVal,oldVal){ this.districtId=-1; this.districtAll=[]; district.forEach(district=>{ if(district.upid==newVal){ this.districtAll.push(district) console.log(this.districtAll); } }) } }, created() { console.log(this.provinceAll); }, }); </script> </body> </html>
Vue中使用过滤器(Filters)来渲染数据是一种很有趣的方式,他不能替代Vue中的methods
、computed
或者watch
,因为过滤器不改变真正的data
,而只是改变渲染的结果,并返回过滤后的版本。在很多不同的情况下,过滤器都是有用的,比如尽可能保持API响应的干净,并在前端处理数据的格式。在你希望避免重复和连接的情况下,它们也可以有效地封装成可重用代码块背后的所有逻辑。不过,在Vue 2.0中已经没有内置的过滤器了,我们必须要自己来构建它们。过滤器只能用于插值表达式中。
全局过滤器是只通过 Vue.filter()的方式来定义的过滤器,用这种方式定义的过滤器可以被所有的Vue实例使用。
<div id="app"> <p>{{createtime | timeFilter}}</p> //2.调用过滤器 </div> <script src="./vue.js"></script> <script> Vue.filter('timeFilter', function(value){ //1.定义全局过滤器 return moment(val).format(yyyy-MM-dd hh-mm-ss); }) new Vue({ el: '#app', data: { createtime:1653374270112 } }); </script>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
案例一:将数字转换为美元的形式。
<div id="app">
<p>{{price | toUSD}}</p>
</div>
<script src="./vue.js"></script>
<script>
Vue.filter('toUSD', function(value){
return '$' + value;
})
new Vue({
el: '#app',
data: {
price: 345.45
}
});
</script>
案例二:串联过滤器,将数字四舍五入成两位有效数字,然后转换为美元表达方式
<div id="app"> <p>{{price | fix(2) | toUSD}}</p> </div> <script src="./vue.js"></script> <script> //方法的第一个参数为数据源,第二个为保留几位小数。 Vue.filter('fix', (num, limit) => { return num.toFixed(limit); }); //转换为美元表达方式 Vue.filter('toUSD', function(value){ return '$' + value; }) new Vue({ el: '#app', data: { price: 345.45 } }); </script>
案例三:替换文本
<div id ="app"> <p>{{msg|str()}}</p> </div> <script> //创建Vue实例,得到 ViewModel var vm = new Vue({ el: '#app', data:{ msg:"没有未来的未来不是我想要的未来" }, methods: {}, filters:{ str(source){ return source.replace(/未来/g,'世界'); } }, }); </script>
练习:定义日期转换的过滤器。
github下载地址:https://github.com/axios/axios
跨域访问:
跨域访问时浏览器的限制,浏览器不允许不同的域之间相互访问(出于安 全的考虑)
哪些情况会构成跨域
1:域名不同 www.taobao.com => www.jd.com
2:ip不同 11.124.8.12 => 10.15.145.12
3:port不同 127.0.0.1:5566 => 127.0.0.1:8080
4:协议不同 https://127.0.0.1:5566 => http://127.0.0.1:8080
5 : 请求的资源不存在,直接报跨域
跨域问题解决:jsonp解决
让服务端信任客户端,允许客户端跨域访问
@CrossOrigin(origins = {"http://127.0.0.1:5500","http://localhost:5500"})
//发送异步请求,调用后端接口,获取用户列表 axios.get("http://localhost:8888/user/findAll") .then(res=>{ //成功回调 console.log(res.data); }) .catch(err=> {//失败回调(除了200,其他都是失败) console.log(err); console.log("????"); }); //分页查询 // axios.get("http://localhost:8888/user/findPage?page=1&size=3") // .then(res=>{ //成功回调 // console.log(res.data); // }) // .catch(err=> {//失败回调(除了200,其他都是失败) // console.log(err); // console.log("????"); // }); axios.get("http://localhost:8888/user/findPage",{params:{page:1,size:3}}) .then(res=>{ //成功回调 console.log(res.data); }) .catch(err=> {//失败回调(除了200,其他都是失败) console.log(err); console.log("????"); });
方式一:通过url传参
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="./lib/vue.js"></script> <!-- 导入axios库文件 --> <script src="./lib/axios.js"></script> </head> <body> <div id ="app"> </div> <script> //创建Vue实例,得到 ViewModel var vm = new Vue({ el: '#app', data:{ }, methods: { }, created() { //发送get请求 axios.get("http://localhost:8080/goods/findAll?name='jack'").then( //请求成功的回调 function(res){ console.log(res.data); } ).catch( //请求失败的回调(404、500、400、403除了200其他都是失败) function(err){ console.log("come in !!") console.log(err); } ) }, }); </script> </body> </html>
注意:
1:解决跨域的问题(浏览器为了安 全做的限制,不是服务端的限制,底层可以通过jsonp的原理去解决)
解决办法在controller类上统一价@CrossOrigin
2:axios成功回调的数据必须通过res.data获取
方式二:通过parms传参
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="./lib/vue.js"></script> <!-- 导入axios库文件 --> <script src="./lib/axios.js"></script> </head> <body> <div id ="app"> </div> <script> //创建Vue实例,得到 ViewModel var vm = new Vue({ el: '#app', data:{ }, methods: { }, created() { //定义参数 var paramsObj = { name:"jack" } //发送get请求 axios.get("http://localhost:8080/goods/findAll",{params:paramsObj}).then( //请求成功的回调 function(res){ console.log(res.data); } ).catch( //请求失败的回调(404、500、400、403除了200其他都是失败) function(err){ console.log("come in !!") console.log(err); } ) }, }); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="./lib/vue.js"></script> <script src="./lib/axios.js"></script> </head> <body> <div id ="app"> username <input type="text" v-model="user.username"> address <input type="text" v-model="user.address"> <input type="submit" value="save" @click="save()"> </div> <script> //创建Vue实例,得到 ViewModel var vm = new Vue({ el: '#app', data:{ user:{ username:"", address:"" } }, methods: { save(){ //发送异步请求(post) axios.post("http://localhost:8888/user/save",this.user) .then(res=>{ console.log(res.data); }) .catch(err=>{ }) } } }); </script> </body> </html>
axios.defaults.timeout = 10000; // 超时时间
axios.defaults.baseURL = apiURL; // baseURL
//设置axios请求拦截器
axios.interceptors.request.use(function(config){
console.log(config);
//统一设置请求头
config.headers.token = "uuid";
return config;
})
//通过axios请求拦截器全局设置请求头
axios.interceptors.request.use( config=>{
config.headers.token = "1234" ;
return config;
})
后台接收请求头的信息
@RequestHeader("token") String token
//设置响应拦截器
axios.interceptors.response.use(res=>
return res.data;
})
//设置响应拦截器
axios.interceptors.response.use(function(res){
console.log(res);
return res.data;
})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="./lib/vue.js"></script> <script src="./lib/axios.js"></script> </head> <body> <div id ="app"> </div> <script> axios.defaults.baseURL = "http://localhost:8888"; axios.defaults.timeout = 3000; //通过axios请求拦截器全局设置请求头 axios.interceptors.request.use(config=>{ config.headers.token = "1234"; console.log(config); return config; }) //通过响应拦截器,全局获取后端返回的data axios.interceptors.response.use(res=>{ return res.data; }) //创建Vue实例,得到 ViewModel var vm = new Vue({ el: '#app', data:{ }, methods: {}, created() { // axios.get("/user/findAll",{headers:{token:"123"}}).then(res=>{ // console.log(res.data); // }) axios.get("/user/findAll").then(res=>{ console.log(res); }) axios.get("/user/findAll").then(res=>{ console.log(res); }) }, }); </script> </body> </html>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
需求:分页+条件查询
查询:条件+分页的查询
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="./lib/vue.js"></script> <script src="./lib/axios.js"></script> </head> <body> <div id ="app"> <input type="text" placeholder="请请输入用户名" v-model="stu.uname"> <input type="text" placeholder="请请输入年龄" v-model="stu.uage"> <input type="submit" value="搜索" @click="search()"><br/><br/> <table width="100%" border="1px" cellspacing="0" cellspadding="0"> <tr> <td>名字</td> <td>年龄</td> </tr> <tr v-for="(item, index) in stuList" :key="index"> <td>{{item.uname}}</td> <td>{{item.uage}}</td> </tr> </table> <span @click="page=p;search()" v-for="(p ) in pages" >[{{p}}] </span> </div> <script> axios.defaults.baseURL = "http://localhost:8080" ; //定义响应拦截器 axios.interceptors.response.use(function(res){ return res.data; }) //定义axios请求拦截器 axios.interceptors.request.use(function(config){ config.headers.token = "xx"; return config; }) //创建Vue实例,得到 ViewModel var vm = new Vue({ el: '#app', data:{ stu:{ }, stuList:[], pages:0, // 总页数 page:1, size:1, }, methods: { search(){ axios.post(`/findPage?page=${this.page}&size=${this.size}`,this.stu).then(res=>{ console.log(res); //res是后台返回的数据 this.stuList = res.data; this.pages = res.pages }) } }, created() { //页面加载,获取第一页数据 this.search(); }, }); </script> </body> </html>
使用postman接口测试
nodejs —> NPM —> vue-cli —> Vue的工程化项目
1.安装nodejs (node-v16.14.2-x64.msi)
https://nodejs.org/en/
2.打开控制台查看版本号
node -v
npm -v
3.使用npm构建项目
npm install -g @vue/cli #安装vue-cli,该步骤需要等一段时间 -g表示全局安装 vue -V #查看vue-cli的版本 vue create my-app #创建名为my-app的项目
- 1
- 2
- 3
4.选择版本 Vue 2
>//或者手动配置 勾选 Router,版本2.x (Vue3 的编程语言为Ts)
5.项目结构
public: 存放静态文件。
- favicon.ico
- index.html
src: 源码文件,开发就在此目录下。
assets:资产,存放文件,图片,css
components:组件
router:路由
views:视图
App.vue:入口组件
main.js:入口程序
import Vue from 'vue' #导入Vue App import App from './App.vue' Vue.config.productionTip = false new Vue({ render: h => h(App), }).$mount('#app') #把Vue挂载到index.html中ID为app的div
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
.gitignore: git的配置文件。
babel.config.js: babel的配置文件,在创建项目的时候才用的脚手架为bable,高级语法转低级语法
package-lock.json:定义了依赖库的下载位置,保证了在项目迁移部署环境的一致性。
package.json: 定义了该项目依赖的类库。
- dependencies:依赖
- devDependencies:依赖的作用范围,只在开发时有效
- eslintConfig:语法检测,书写的代发必须符合eslint规范
- browserslist:开发的vue项目,满足市面上99%的浏览器兼容
6.启动项目
Ctrl+~ #打开终端 npm run serve #启动项目(默认端口为8080)
- 1
- 2
执行命令:
npm run build
将生成的dist目录下的文件放入到tomcat或者nginx下,启动服务器,即可访问。
组件化开发是在ES6中提出的,可以提高页面的复用率,提高开发效率,便于团队协作,是一套模板化的代码,要有<template>
、<script>
、<style>
三个标签,分别用来定义布局、脚本和样式。而且<template>
下必须有一个根节点。
HelloWorld.vue
<template> <div> <!-- template的根节点,是必须的 --> <h1 class="title">{{msg}}</h1> </div> </template> <script> export default { <!-- 向外保留成员,表示向外暴露该组件 --> data() { return { msg: 'Hello World' } } } </script> <style> .title{ color: red; } </style>
App.vue
<template> <div> <p>{{article}}</p> <Helloworld></Helloworld> <!-- 在Helloworld.vue中的组件 --> </div> </template> <script> /** * 引入HelloWorld.vue组件,使用Helloworld变量来接收,接收变量的组件 * 可以叫任何名字,但是推荐使用和导入组件保持一致。 */ import Helloworld from './components/HelloWorld.vue' export default { /** * 需要在当前组件中来定义引入的组件,接收的形式可以有二种: * * components: {HelloWorld} 最原始的写法为{Helloworld:Helloworld},第一个Helloworld * 在当前组件中使用的名字,可以随意更改,第二个Helloworld是上面import引入的时候用来接收的变 * 量名。如果只写一个表示当前组件中使用的名字和变量名一致。 */ components: {Helloworld}, data(){ //组件化编程必须使用定义data方法 return { article: '路透社20日援引伊朗法尔斯通讯社消息称' }; } } </script> <style> </style>
import Vue from 'vue' //引入vue
import App from './App.vue' //引入自己定义的App.vue,使用变量App来接收
new Vue({
render: h => h(App), //将App组件渲染到index.html中。
}).$mount("#app")
render是Vue中的一个方法,方法的定义形式如下:
// render最原始的,而传入的参数createElement又是一个函数,用来生成dom结构
render: function(createElement){
}
// 按照ES6的箭头函数的写法,进行第一次演变
render: createElement => createElement(模板)
// 将上面的createElement变为h,那么就得到最终的形式
render: h => h(App)
$mount(“#id”)该方法的作用是先实例化Vue对象,接着在挂载到指定Id的节点上,和在**new Vue
**的时候使用el指定要渲染的节点的形式是一样的,只是换了种形式而已。
- 计算器
- tap选项卡
- 购物车
- 表单操作
- 评价功能
- 打豆豆
当你能够独立的完成如上案例,表示你已经比较深入的理解VUE了 _
父组件 App.vue
<template> <div> <h1>Hello World</h1> <!-- 前面一个msg标识子组件用于接收的变量名, 引号中的msg是当前组件的值 第一个add是子组件用于接收的变量名,第二个add是当前组件的方法名 --> <child :msg="msg"/> </div> </template> <script> import child from './Child.vue' export default { components: { child }, data() { return { msg: '这个信息来源于父组件' }; } } </script> <style></style>
子组件 Child.vue
<template>
<div>
<p>{{msg}}</p>
<button @click="addItem" />
</div>
</template>
<script>
export default {
// 使用props接收父组件传递过来的值
props: ['msg']
}
</script>
<style></style>
父组件 App.vue
<template> <div> <input type="text" v-model="value"> <hr> <Child @dosomething="changeValue"/> </div> </template> <script> import Child from './components/Child.vue' export default { components: { Child }, data() { return { value: '' } }, methods: { changeValue(value) { this.value = value; } } } </script> <style> </style>
子组件 Child.vue
<template> <div> <button @click="dosomething">子组件按钮</button> </div> </template> <script> export default { methods: { dosomething() { // 调用父组件绑定的事件 dosomething,然后调用changeValue方法,并传值 this.$emit('dosomething', '张某人'); } } } </script> <style> </style>
父组件 App.vue
<template> <div> <input type="text" v-model="value"> <button @click="changeValue">取子组件的值</button> <hr> <Child ref="child"/> </div> </template> <script> import Child from './components/Child.vue' export default { components: { Child }, data() { return { value: '' } }, methods: { changeValue() { this.value = this.$refs.child.value; } } } </script> <style> </style>
子组件 Child.vue
<template> <div> <p>我是子组件,我中间定义了一个value='张某人'的数据</p> </div> </template> <script> export default { data() { return { value: '张某人' } } } </script> <style> </style>
插槽的作用说白了就是一个占位的作用。
父组件 App.vue
<template> <List> <!-- 可以简写为这种形式 <template #title> --> <template v-slot:title> <h2>插槽案例</h2> <button class="btn btn-danger btn-sm">点击</button> </template> <!-- 可以简写为这种形式 <template #title="props"> --> <template v-slot:item="props"> <h3>插槽属性</h3> <p>属性值:{{props}}</p> </template> </List> </template> <script> import List from './components/List.vue' export default { components: { List } } </script> <style> .site-header { text-align: center; } </style>
子组件 Child.vue
<template> <div> <slot name="title"></slot> <slot name="item" v-bind="person"></slot> <!-- 组件属性 --> </div> </template> <script> export default { data() { return { person: {age: 10, name: 'zhangsan'} } } } </script> <style> </style>
routes:[ { path:'/home/:val', component:Home, props:true } ]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
export default{ props:['val'] }
- 1
- 2
- 3
this.$router.push({ path:`/user-detail`, query:{ id:uId, name:'张三' } })
- 1
- 2
- 3
- 4
- 5
- 6
- 7
mounted(){ let id = this.$route.query.id }
- 1
- 2
- 3
vue2.X版本中,官方推荐的网络请求的工具是axios。
npm install axios vue-axios --save
新建Base.vue文件,文件内容如下:
<script>
const BASE_URL = "http://localhost:8081"
export default {
BASE_URL
}
</script>
import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
import Base from './Base.vue'
Vue.use(VueAxios, axios); //顺序有关系
axios.defaults.baseURL = Base.BASE_URL //配置基本地址
new Vue({
render: h => h(App),
}).$mount('#app')
this.axios.get('/user'
/** 可以通过如下方式,添加请求头信息
,{
headers: {
'token': 'hyfetrrabcpo'
}
}
*/
)
.then((resp) => { // 请求成功
this.users = resp.data;
}, (error) => { //请求失败
window.console.log(error); //不能直接用console
})
this.axios.post('/user', {name:'zhangsan', id: 10}) //后台必须要用json接收
.then((resp) => {
this.users = resp.data;
}, (error) => {
window.console.log(error); //不能直接用console
})
this.axios.delete('/user/56')
.then((resp) => {
this.users = resp.data;
}, (error) => {
window.console.log(error); //不能直接用console
})
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。
npm install vue-router@3.5.4 --save
新建一个文件夹叫做router,然后在里面定义一个index.js文件,在该文件中配置路由信息:
import Vue from 'vue' import Router from 'vue-router' import Home from '../views/Home.vue' import About from '../views/About.vue' Vue.use(Router) //使用插件 export default new Router({ linkActiveClass: 'active', //选中状态下默认添加的样式 routes: [ { path: '/home', component: Home }, { path: '/about', component: About }, { path: '/', redirect: '/about' //根路径默认会重定向到/about路径 } ] })
import Vue from 'vue'
import App from './App.vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
import Base from './Base.vue'
import router from './router'
Vue.use(VueAxios, axios); //顺序有关系
axios.defaults.baseURL = Base.BASE_URL
new Vue({
render: h => h(App),
router
}).$mount('#app')
使用<router-link>
标签设置路径,to属性设置路由路径:
<router-link to="/home" class="list-group-item">Home</router-link>
<router-link to="/about" class="list-group-item">About</router-link>
使用<router-view>
标签,将对应的路由组件设置到这个标签当中:
<router-view></router-view>
在路由的配置中使用children来配置子路由。
children: [
{
path: '/home/game',
component: Games
}
]
在使用路由的过程中,经常会碰到路由参数的传递,那么传递方式大概有三种。
方式一:
路由配置:
{path:'/user/:id', component:userDetail, props:true}
路由请求:
<router-link :to="'/user/' + user.id">{{user.name}}</router-link>
取值:
在userDetail中使用 props: {id: String} 来接收数据
方式三:
路由配置:
{path:'/user', name:'userDetail', component:userDetail}
路由请求:
<router-link :to="{path:'/user', query:{id:user.id}}">{{user.name}}</router-link>
取值:
mounted() {
this.id = this.$route.query.id; //用户刷新的时候有用
},
watch:{ //监听路由的变化
$route: {
handler(val) {
this.id = val.query.id;
}
}
}
方式一:
实现跳转: this.$router.push({ path: '/user', query: {id:id} }); 取值: mounted() { this.id = this.$route.query.id; }, watch:{ $route: { handler(val) { this.id = val.query.id; } } }
方式二:
实现跳转:
this.$router.push({
path: '/user',
query: {id:id}
});
取值:
props: {
id: String
}
router.beforeEach((to,from,next) =>{
next();
});
vuex是对vue项目进行状态管理的js库,对于所有的组件来说,它是一个中央存储,这种模式就保证了只能按照特定的模式来更改状态。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dwDDC3z2-1663847834589)(image/vuex.png)]
state
说的直白点就是存储数据的地方。
actions
通过异步的方式更改状态值,但是不能直接更改,需要借助于mutations来更改。
mutations
通过直接同步的方式更改状态。
getters
类似于计算属性,通常是需要通过state来间接计算得到的值。
modules
一个项目中因为模块的原因,存在着各种不同的状态,需要按照模块来划分。
npm install vuex --save
新建一个文件夹,名字叫store,在文件夹中新建一个文件,文件名叫index.js,文件内容如下:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); //state const state = { todos:[{title:'工作一', complete:true}] } // actions const actions = { // 第一个参数必须是context, 第二个参数是需要的业务数据 addTodo(context, todo){ // 通过commit的方式提交个mutations, 真正实现对状态修改的其实是mutations context.commit('addTodo', todo) } } // getter,类似于计算属性,需要根据state来计算出其他想要的属性 const getters = { completedTodoNumber: state => { return state.todos.reduce((preTotal, current) => preTotal + (current.complete ? 1 : 0), 0) } } //操作 const mutations = { //添加待办事项,第一个参数必须是state, 第二个参数是传递过来的数据 addTodo(state, todo) { state.todos.unshift(todo) } } // 对外暴露Vuex.Store的对象,在其他任何组件中都可以使用 $store来进行操作 export default new Vuex.Store({ state, mutations, actions, getters })
import Vue from 'vue'
import App from './App.vue'
import store from './store'
new Vue({
store, //引入store
render: h => h(App)
}).$mount("#app");
this.$store.state.todos //获取状态值
this.$store.commit('addTodo', todo); //通过mutations中的方法更新状态
this.$store.dispatch('addTodo', todo); //通过actions中的方法异步更新状态
this.$store.getters.completedTodoNumber; //获取getters中的属性
import {mapState, mapActions, mapGetters, mapMutations} from 'vuex'
computed: {
...mapState(['todos']), //扩展运算符, 在当前组件中直接使用this的方式调用
...mapGetters(['completedTodoNumber'])
},
methods: {
//引号中的内容为actions中定义的方法名, 可以直接使用this.addTodo来调用。
...mapActions(['addTodo']),
...mapMutations(['addTodo'])
}
A. 新建一个shopping目录,目录下新建index.js文件,文件内容如下:
const state = { todos:[{title:'工作一', complete:true}] } const actions = { addTodo(context, todo){ context.commit('addTodo', todo) }, delDone(context) { context.commit('delDone') }, delByIndex(context, index) { context.commit('delByIndex', index); } } const getters = { completedTodoNumber: state => { return state.todos.reduce((preTotal, current) => preTotal + (current.complete ? 1 : 0), 0) } } //操作 const mutations = { //添加待办事项 addTodo(state, todo) { state.todos.unshift(todo) }, delDone(state) { state.todos = state.todos.filter(todo => !todo.complete) }, delByIndex(state, index) { state.todos.splice(index, 1); } } export default { state, actions, getters, mutations }
B. 在store下的index.js文件中写入如下内容:
import Vue from 'vue'
import Vuex from 'vuex'
import shopping from 'shopping'
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
shopping
}
})
C. 使用
获取对应模块的state值方式一:
...mapState({todos: state=>state.shopping.todos})
获取对应模块的state值方式二:
todos: function() {
return this.$store.state.shopping.todos;
}
至于getters、actions、mutations都被注册到全局上,和之前的使用方式一样。
1.spring boot跨域支持
A. 在controller或者对应的方法上加上如下代码
@CrossOrigin(origins = {"http://localhost:8080"})
B. 基于过滤器的跨域支持
@Configuration public class MyConfiguration { @Bean public FilterRegistrationBean corsFilter() { UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("http://domain1.com"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); source.registerCorsConfiguration("/**", config); FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); bean.setOrder(0); return bean; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。