使用jQuery的复杂性问题
使用jQuery进行前后端分离开发,即可以实现前后端交互(ajax),又可以完成数据渲染
存在的问题:jQuery需要通过HTML标签拼接、DOM节点操作完成数据的显示,开发效率低且容易出错,渲染效率较低
vue是继jQuery之后的又一优秀的前端框架;专注于前端数据的渲染--语法简单、渲染效率高
前端框架
前端三要素:HTML、CSS、JavaScript
HTML决定网页结构
CSS决定显示效率
JavaScript决定网页功能(交互、数据显示)
UI框架:
Bootstrap
amazeUI
Layui
JS框架:
jQuery(jQuery UI)
React
angular
node.js ---- 后端开发
vue集各种前端框架的优势发展而来
MVVM
项目结构经理的三个阶段
后端MVC我们就可以理解为单体架构,流程控制是由后端控制器来完成
前端MVC前后端分离开发,后端只负责接收响应请求
MVVM前端请求后端接口,后端返回数据,前端接收数据,并将接收的数据设置VM,HTML从vm取值
Vue被设计为可以自低向上逐层应用。Vue的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合
离线引用:下载vue的js文件,添加到前端项目,在网页中通过script标签引用vue.js文件
CDN引用
{{str}}
基本类型数据和字符串
{{code}} {{str}} ------------------------- data:{ code:10, str:"test" }
对象类型数据
支持ognl语法
{{stu.stuNum}} {{stu.stuName}} ----------------------------- data{ stu:{ stuNum:"100001", stuName:"张三", stuGender:"M", stuAge:20 } }
条件 v-if
//条件不成立则不显示
------------------------------------------------------- data:{ stu:{ stuNum:"100001", stuName:"张三", stuGender:"M", stuAge:20 } }
循环 v-for
序号 | 学号 | 姓名 | 性别 | 年龄 |
---|---|---|---|---|
{{index+1}} | {{s.stuNum}} | {{s.stuName}} | {{s.stuAge}} |
v-bind绑定标签属性
v-bind:可简写为 :
------------------------------------ data{ str:"从前有座⼭", stu:{ stuImg:"img/01.jpg" } }
表单标签的双向绑定 v-model
只能使用在表单输入标签
v-model:value 可以简写为 v-model
------------------------------------ data{ str:"从前有座⼭" }
每个使用vue进行数据渲染的网页文档度需要创建一个Vue实例--ViewModel
vue实例生命周期--vue实例从创建到销毁的过程
创建vue实例(初始化data、创建el)
数据挂载(将vue实例data中的数据渲染到网页HTML标签)
重新渲染(当vue的data数据发生变化,会重新渲染到HTML标签)
销毁实例
为了便于开发者在vue实例生命周期的不同阶段进行特定的操作,vue在生命周期四个阶段的前后分别提供了一个函数,这个函数无需开发者调用,当vue实例到达生命周期的指定阶段会自动调用对应的函数
data中的属性可以通过声明获得,也可以通过在computed通过计算获得
特性:计算属性所依赖的属性值发生变化会影响计算属性的值同时发生变化
示例
{{str3}}
侦听器,就是data中属性的监听器,当data中的属性值发生变化就会触发侦听器函数的执行
{{str3}}
我们可以使用mustache语法将vue中data的数据绑定到HTML标签及标签的属性,如何将data中的值绑定到标签的class及style属性呢
WH2010Wh2021wh2021wh2021
v-if
在html标签可以添加v-if指令指定一个条件,如果条件成立则显示此HTML标签,如果不成立则不显示当前标签;
条件可以是一个表达式也可以是一个具体的bool类型值
从前有座⼭
从前有座⼭
v-else
从前有座⼭
⼭⾥有座庙
v-else-if
优秀
良好
中等
及格
不想理你
v-show
从功能上将v-show和v-if作用是相同的,渲染过程有区别
v-if是真正的条件渲染,因为他会确保在切换过程中条件内的事件监听器和子组件适当的被销毁和重建
v-if也是惰性的:如果在初始渲染时条件为假,则什么也不做--直到条件第一次变为真时,才会开始渲染条件块
相比之下,v-show就简单得多--不管初始条件是什么,元素总是会被渲染,并且只是简单地基于css进行切换
一般来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show较好;如果在运行时条件很少改变,则使用v-if较好
将集合数据以表格、列表的形式显示
在使用vue进行数据渲染时,如果使用原生js事件绑定(例如onclick),如果需要获取vue实例中的数据并传参则需要通过拼接来完成
vue提供了v-on指令用于绑定各种事件(v-on:click),简化了从vue取值的过程,但是触发的方法需要定义在vue实例的methods中
v-on:clicl可以缩写为@click
学号 姓名 性别 年龄 操作 {{s.stuNum}} {{s.stuName}} {{s.stuGender == 'M'? '男':'女'}} {{s.stuAge}}
学号 姓名 性别 年龄 操作 {{s.stuNum}} {{s.stuName}} {{s.stuGender == 'M'? '男':'女'}} {{s.stuAge}}
学号 姓名 性别 年龄 操作 {{s.stuNum}} {{s.stuName}} {{s.stuGender == 'M'? '男':'女'}} {{s.stuAge}}
当使用v-on进行事件绑定的时候,可以添加特定后缀,设置事件触发的特性
事件修饰符使用示例
事件修饰符
.prevent消除元素的默认事件
.stop组织事件冒泡(组织子标签向上冒泡)
.self设置只能自己触发事件(子标签不能触发)
.once限定事件只触发一次
按键修饰符
按键修饰符就是针对键盘事件的修饰符,限定那个按键会触发事件
.enter
.tab
.delete(捕获“删除”和“退格”键)
.exc
.space
.up
.down
.left
.right
除了以上vue提供了按钮的别名之外,我们还可以根据键盘为按键自定义别名 键盘码
示例
系统修饰符
组合键
示例ctr+j触发事件
.ctrl
.alt
.shift
.meta windows键
表单输入绑定,即双向绑定:就是能够将vue实例的data数据渲染到表格输入视图,也能够将输入视图的数据同步更新到vue实例的data中
A 1 B 2 C 3 D 4
篮球
乒乓球
羽毛球
足球
接口名称 | |
---|---|
功能描述 | 根据关键字搜索音乐信息 |
请求URL | http://47.96.11.185:9999/music/search |
请求方式 | GET|POST |
请求参数 | s string[必须]搜索关键字 limit[可选]返回的搜索结果的条数,默认为10 type int [可选]搜索类型(1单曲 10歌曲),默认为1 offset int[可选]搜索结果的偏移 |
返回结果 |
java -jar music-1.0.0.jar
音乐搜索
音乐播放
在music.html中定义音频播放器(定义在vue的容器之外)
给播放器按钮绑定点击事件触发的函数doPlay
在doPlay中执行播放
组件,就是将通用的HTML模块进行封装--可复用
组件注册
将通用的HTML模块封装注册到vue中
Vue.component("header-bar",{ });
组件引用
定义组件需要依赖vue.js,在引用自定义组件的js文件之前要先引用vue.js
组件的引用必须在vue实例el指定的容器中
自定义组件的结构
data定义组建的模板渲染的数据
template组建的HTML模块
methods定义组件中的标签时间绑定的js函数
Vue.component("header-bar",{ data:function(){ //组件中的data是通过函数返回的对象 return{ title:"Java2010", count:0 } }, template:``, methods:{ //组建中定义的函数 childMethod:function(){ count++; }, test:function(){ alert("aaaa") } } });
点击次数:{{count}} 1233213123213 {{title}}
组件的封装
组件复用
vue实例本身就是一个组件(模板就是el指定容器,data就是组件数据,methods就是组件的事件函数)
在vue实例指定的el容器中引用的组件称为子组件,当前vue实例就是父组件
父传子
vue实例引用组件的时候,传递数据到引用的组件中
子传父
通过子组件的按钮“调用”父组件的函数,通过函数传值
当我们自定义vue组件时,允许组件中的部分内容在调用组件时进行定义--插槽
插槽的使用
在自定义组件时通过slot标签在组建的模板中定义插槽
Vue.component("header-bar",{ data:function(){ //组件中的data是通过函数返回的对象 return{ //title:"Java2010", str2:"子组建中的数据", count:0 } }, template:``, methods:{ //组建中定义的函数 childMethod:function(){ count++; }, test:function(){ this.$emit("my-event",this.str2) } }, props:["title"] });
点击次数:{{count}} 1233213123213 {{title}}
在父组件中调用此组件时,指定插槽填充的模板
具名插槽
当组件中的插槽>1时,需要给组件中的slot标签添加name属性指定插槽的名字
定义组件
Vue.component("page-frame",{ template:`` });
引用组件template
asdasdsad qweqwewqe tryrtytr
插槽作用域
定义组件时,将组件中的数据绑定到slot标签
Vue.component("page-frame",{ template:``, props:["title","cr"], data:function(){ return { songs:[ {},{} ] }; } });
引用组件时,在填充插槽的模板上使用slot-scopt属性获取插槽绑定的值
序号 歌曲ID 歌曲名 歌⼿ 专辑 时⻓ 操作 {{index+1}} {{song.id}} {{song.name}} {{artist.name}} {{song.album.name}} {{ Math.floor( Math.round(song.duration/1000)/60) < 10 ? '0'+Math.floor( Math.round(song.duration/1000)/60) : Math.floor( Math.round(song.duration/1000)/60) }} : {{ Math.round(song.duration/1000)%60 <10 ? '0'+( Math.round(song.duration/1000)%60 ) : Math.round(song.duration/1000)%60 }}
veu可以实现数据的渲染,但是如何获取数据呢?
vue本身不具备通信能力,通常结合axios 一个专注于异步通信的js框架来使用
axios数据通信
vue数据渲染
原声ajax --实现步骤复杂
jQuery笨重
axios 简介、高效,对RESTful支持良好
axios提供了多种异步请求方法,实现对RESTful风格的支持
get请求
axios.get(url).then(fn);
axios.get(url,{}).then(fu);
//使⽤axios的get请求传递参数,需要将参数设置在params下 axios.get("http://localhost:9999/music/detail",{ params:{ id:"25640392" } }) .then(function(res){ console.log(res); });
post请求
axios.post(url,{}).then(fn)
axios.post("http://localhost:9999/music/search",{s:"阿刁"}) .then(function(res){ console.log(res); });
自定义请求
自定义请求:自定义请求方式、请求参数、请求头、请求体(post)
axios({ url:"http://localhost:9999/music/search", method:"post", params:{ //设置请求⾏传值 s:"成都", limit:15 }, headers:{ //设置请求头 }, data:{ //设置请求体(post/put) } }).then(function(res){ console.log(res) });
其他
delete
put
option
axios回调函数的参数res
res并不是接口返回的数据,而是表示一个响应对象;res.data才表示接口响应的数据
箭头函数
router是由vue官方提供的用于实现组件跳转的插件
离线
在线
使用案例
⾸⻚ Java HTML5 Python
通配符
*可以匹配任意路径
例如:
/user-*匹配所有以user-开头的任意路径
/* 匹配所有路径
index:{{$route.params.id}}
`}; const t2 = {template:`Java
`}; const t3 = {template:`HTML
`}; const t4 = {template:`PYTHON
`}; const t5 = {template:`此路徑不存在
`}; const myrouter = new VueRouter({ routes:[ {path:"/a/:id",component:t1}, {path:"/b",component:t2}, {path:"/c",component:t3}, {path:"/d",component:t4}, {path:"/*",component:t5}, {path:"/user-*",component:t5} ] }) var vm = new Vue({ el:"#container", router:myrouter });注意:如果使用通配符定义路径,需要注意路由声明的顺序
路由参数
/a/:id 可以匹配/a/开头的路径
⾸⻚
优先级
如果一个路径匹配了多个路由,则按照路由的配置顺序:路由定义的越早优先级就越高
在以及路由的组件中显示二级路由
⾸⻚ ⾸⻚-c1 ⾸⻚-c2
push()
push()参数
//1.字符串 myrouter.push("/a"); //2.对象 myrouter.push({path:"/a"}); //3.命名的路由 name参数指的是定义路由时指定的名字 myrouter.push({name:"r1",params:{id:101}}); //4.URL传值,相当于/a?id=101 myrouter.push({path:"/a",query:{id:101}});
replace()
功能与push一致,区别在于replace()不会向history添加新的浏览记录
go()
参数为一个整数,表示在浏览器历史中前后/后退多少相当于 window.history.go(-1)的作用
命名路由:在定义路由的时候可以给路由指定name,我们在进行路由导航可以通过路由的名字导航
t1
t1 t2
重定向
访问/b,重定向到/a
路径A 路径B
根据路由命名重定向
const myrouter = new VueRouter({ routes:[ { path:"/a", name:"r1", component:t1 }, { path:"/b", //redirect:"/a" //根据路由路径重定向 redirect:{name:"r1"} //根据路由命名重定向 } ] });
路由别名
路径A 路径wahaha(别名)
可以通过/url/:attr方式实现通过路由传值给组件
路径A
通过props穿参
路径A