- 什么是VUE
- 如何使用VUE
- MVVM
- 绑定原理
- 指令
一. 什么是VUE:
- 什么是:
(1). 第三方开发的 —— 下载
(2). 基于MVVM设计模式的 ?
(3). 渐进式的 —— 可以逐步在项目中使用vue的部分继承。而不要求必须把整个项目都改为vue。
(4). 纯前端js —— 只要有浏览器就可以运行,和后端nodejs无关。
(5). 框架 —— 自动化,避免大量重复劳动 - 为什么: 简化开发,避免重复劳动!
- 何时: 今后,凡是以数据操作(增删改查)为主的项目,都适合用vue等框架来实现。
比如: 饿了么,美团,滴滴,京东,淘宝,头条,知乎,微博... - 问题:
(1). 兼容性问题
(2). 难以接受
二. 如何使用:
-
下载: cn.vuejs.org
(1). 下载vue.js文件,引入HTML中使用:
a. 开发版: 未压缩版,包含完整的注释,代码格式和见名知义的变量名。而且,还包含极其友好的错误提示信息。
适合学习和开发之用
b. 生产版: 压缩版,去掉了所有注释,代码格式,极简化了变量名。而且,去掉了友好的错误提示信息。
适合生产环境上线使用。
(2). 安装脚手架
_first_vue.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>Document</title>
<!--先引入vue.js-->
<script src="js/vue.js"></script>
</head>
<body>
<!--VUE 3步-->
<!--1. 先做界面: 3个要求
1.1 统一的要求: 界面中所有元素,都必须包裹在一个唯一的父元素下,习惯上<div id="app"></div>
1.2 找到界面中将来可能随程序自动变化的位置,用专门的语法:{{变量名}}来标记/占位
本例中:?
1.3 找到界面中将来可能触发事件的元素,用专门的语法: @事件名="事件处理函数名" 来标记
本例中: ?-->
<div id="app">
<button @click="minus">-</button>
<span>{{n}}</span>
<button @click="add">+</button>
</div>
<script>
//2. 创建一个new Vue()对象,来监控div所包含的区域。
var vm=new Vue({
//vue对象中,必须用el属性,告诉new Vue()要监控的区域是哪里: (el其实是element的缩写)
// id选择器
el:"#app",
//3. 定义模型对象,来保存界面中所需的所有变量和事件处理函数
//什么是模型对象: 就是专门替界面保存变量和事件处理函数的特殊的对象
//3.1 先创建一个data:{}来保存界面中所需的所有变量和初始值
//本例中: 因为界面上只需要一个变量n,所以data中才需要1个变量n
data:{
n:0
},
//3.2 再创建一个methods:{}来保存界面中所需的所有事件处理函数
//本例中: 因为界面中需要2个事件处理函数,所以methods中应该定义两个函数
methods:{
add(){
this.n++;
},
minus(){
if(this.n>0){
this.n--;
}
}
}
//强调:
//3.2.1 methods中的事件处理函数中,如果要操作data中的变量,必须加this.
//3.2.2 methods中的事件处理函数中,根本不用考虑如何从界面取值,也不用考虑如何将新值放回界面,只需要专门考虑如何把data中的变量值修改正确即可!
//new Vue()会自动保持界面中变量n和data中变量n同步:
//开局时,data中n是几,new Vue()就把n的值送到页面上,对应位置显示给人看
//当methods中修改了n的值,new Vue()会自动把n的新值自动更新到界面中n所在的位置给人看
});
console.log(vm);
</script>
</body>
</html>
运行结果: 三. MVVM:
1.旧的前端程序划分为三部分:
(1). HTML: 专门定义网页内容
(2). CSS: 专门定义网页内容的样式
(3). JS: 专门为网页添加交互行为
- 问题: HTML和CSS功能太弱,甚至不支持程序该有基本功能: 变量,运算,分支、循环。所以,哪怕一点儿修改,都要麻烦js来操作。导致js的任务量非常繁重,且存在大量重复劳动。
3. 解决: MVVM设计模式,是对前端三大部分的重新划分。
(1). 界面(View):
a. 包括HTML+CSS
b. 增强版: 支持程序的基本功能: 变量,运算,分支和循环.
(2). 模型对象(Model):
a. 什么是: 专门替界面保存所属的变量和函数的特殊对象
b. 今后,只要界面上需要用到哪些变量和函数时,都要保存在模型对象中
(3). 视图模型(ViewModel)
a. 什么是: 专门自动将模型对象中的变量和函数,自动传递到界面上指定位置的特殊对象
b. 何时: 今后,只要希望有人自动将模型对象中的变量和函数自动运送到界面上,都要定义视图模型。
4. Vue框架如何实现MVVM设计模式的: Vue的绑定原理
(1). 创建new Vue()对象, 2件事:
a. 隐藏data中的原变量,自动为data中原变量创建访问器属性。从此,在new Vue中使用的任何变量,其实都只能是访问器属性。
b. 引入methods并打散methods为多个函数。
1). 原methods中的函数,不再隶属于methods,而是直接隶属于new Vue()对象了
2). 所以,methods中的函数打散后与访问器属性平级,所以,methods中的方法,想访问访问器属性变量,必须加this.
(2). new Vue()中el:"#app"在指引new Vue()对象去创建虚拟DOM树
a. 扫描el属性:"#app"所指的页面区域的真实DOM树,只找出可能发生变化的元素,保存进虚拟DOM树中
b. 今后,只要new Vue()中修改了变量,其实就是修改了访问器属性。
1). 访问器属性就会向虚拟DOM树发出通知
2). 虚拟DOM树扫描内部所有可能发生变化的元素,找出受本次变量修改影响的个别元素。
3). 虚拟DOM树利用内部已经封装好的DOM操作,只修改页面上受本次影响的元素。不受本次影响的元素,不会改变。
(3). 总结: Vue的绑定原理=访问器属性+虚拟DOM树
5. 虚拟DOM树的优点:
(1). 小 —— 只包含受影响的元素
(2). 遍历快
(3). 更新效率高—— 只更新受影响的元素,不受影响的元素保持不变。
(4). 避免重复编码—— 已经封装了DOM增删改查操作,可自动更新页面内容。
四. 绑定语法: 学名: 插值语法 Interpolation
- 什么是: 专门在HTML语言中标记可能发生变化的元素内容的特殊语法
- 何时: 今后,只要一个元素的内容,在程序执行过程中,可能会被改变,都要用绑定语法来标记
3. 如何: <元素>其它文本{{变量名}}其它文本</元素>
4. 结果:
(1). 首次加载页面时,new Vue()会自动去data中查找同名的变量,并将变量值,替换{{}}所在的位置
(2). 今后只要在new Vue()中修改了{{}}中的变量后,new Vue()都会自动将变量的新值重新替换{{}}的位置。
- {{}}内部: 和模板字符串的${}中规则一样
(1). 可以放: 有返回值的语法正确的js表达式
比如: 变量, 算术计算, 三目, 访问数组元素, 创建对象, 调用方法。
(2). 不可以放: 分支和循环以及没有返回值的js表达式 - 示例: 使用绑定语法展示各种数据:
_{{}}.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>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<h3>Welcome {{uname}}</h3>
<h3>性别:{{sex==1?"男":"女"}}</h3>
<h3>小计:¥{{(price*count).toFixed(2)}}</h3>
<h3>下单时间: {{new Date(orderTime).toLocaleString()}}</h3>
<h3>今天星期{{week[day]}}</h3>
</div>
<script>
new Vue({
el:"#app",
data:{
uname:"dingding",
sex:1,
price:12.5,
count:5,
orderTime:1614158191101,
week:["日","一","二","三","四","五","六"],
day:new Date().getDay()
}
})
</script>
</body>
</html>
运行结果:
Welcome dingding
性别:男
小计:¥62.50
下单时间: 2021/2/24下午5:16:31
今天星期二
五. 指令(directive):
- 问题: 如果一个元素的属性值随程序自动变化,则如果用{{}}标记,会报错!
- 解决: 今后,只要元素的属性可能发生变化,都要用"指令"来代替{{}}
3. vue中包括: 13种:
(1). v-bind:
a. 什么是: 专门用来标记属性值变化的特殊指令
b. 如何:
1). 标准: <元素 v-bind:属性名="变量或js表达式">
html地盘 | js的地盘 |
2). 简写: <元素 :属性名="变量或js表达式">
c. 原理: new Vue()只要扫描到":",就会先执行=右侧""中的js变量或表达式。然后用变量值或js表达式的运行结果,作为当前属性的属性值!
d. 强调:
1). 一旦属性上加了:,则不要再加{{}}了!""就起到了{{}}的作用。
2). ""之内变成了js的语法天下!必须遵守js的语法!
e. 示例: 根据pm25数值,显示不同的图片
4_v-bind.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>根据程序中PM25的数值显示不同的表情</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<!--哪里可能随程序自动改变?-->
<img :src="pm25<100?'img/1.png':pm25<200?'img/2.png':pm25<300?'img/3.png':'img/4.png'">
<h3>{{pm25<100?'img/1.png':pm25<200?'img/2.png':pm25<300?'img/3.png':'img/4.png'}}</h3>
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
//程序中只保存pm2.5的数值,不保存图片路径
pm25:160
}
})
//运行后,F12打开控制台,console,输入vm.pm25=数值,观察页面上图片的变化.
</script>
</body>
</html>
运行结果: (2). v-show:
a. 什么是: 专门根据条件控制一个元素的显示隐藏
b. 如何: <元素 v-show="变量或js表达式">
c. 原理: new Vue()只要扫描到v-show,就会先执行=右边""中的变量或js表达式:
1). 如果=右边的变量或js表达式结果为true,则当前元素正常显示
2). 如果=右边的变量或js表达式结果为false,则当前元素隐藏(new Vue()自动将v-show替换为display:none)!
d. 示例: 点按钮弹出框
5_v-show.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
<style>
#pop{
position:fixed;
top:50%;
left:50%;
width:300px;
height:100px;
margin-left:-150px;
margin-top:-50px;
background-color:lightBlue
}
#pop>a{
float:right;
margin-right:20px;
text-decoration:none;
}
</style>
</head>
<body>
<!--VUE 3步
1. 做界面:
1.1 唯一父元素
1.2 找可能发生变化的元素
本例中:div的显示隐藏状态有可能变化
1.3 找触发事件的元素
本例中:
button触发事件,显示对话框
a触发事件,隐藏对话框
-->
<div id="app">
<button @click="show">click me</button>
<div v-show="visible" id="pop">
<a href="javascript:;" @click="hide">×</a>
</div>
</div>
<script>
//2. 创建new Vue()对象,监控id为app的区域
new Vue({
el:"#app",
//3. 创建模型对象:
//3.1 创建data对象
//本例中: 只用到一个变量visible,所以
data:{
visible:false, //专门用来保存弹出框的显示隐藏状态。开局,因为弹出框隐藏,所以变量值为false。
},
//3.2 创建methods对象
//本例中: 因为界面上需要2个事件处理函数,所以,methods中也应该保存2个事件处理函数
methods:{
show(){
this.visible=true;
},
hide(){
this.visible=false;
}
}
})
</script>
</body>
</html>
运行结果: (3). v-if和v-else:
a. 什么是: 专门根据条件在两个元素之间二选一显示隐藏
b. 如何:
<元素1 v-if="变量或js表达式">
<元素2 v-else>
强调: v-if和v-else两个元素之间必须紧挨着写,不能插入任何其他元素.
c. 原理: new Vue()扫描到v-if时,总是先执行=右边""中的变量和js表达式:
1). 如果v-if=右边的变量或js表达式返回true,则显示v-if所在的元素,而删除v-else所在元素
2). 如果v-if=右边的变量或js表达式返回false,则删除v-if所在的元素,而保存v-else所在的元素
d. 问题:为什么已经删除的元素,后来还能回到页面上
原理: 每次删除的指示真实DOM树中的元素对象。而虚拟DOM树中始终同时保存着v-if和v-else两个元素对象。每次变量发生变化时,并不是直接扫描真实DOM树,而是扫描虚拟DOM树中两个元素对象,决定这次派谁上场!
e. v-if和v-show的差别:
1). v-show: 用display:none隐藏元素
2). v-if: 用删除元素方式来达到隐藏的目的
f. 示例: 切换登录状态:
6_v-if_v-else.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<!--VUE 3步
1. 做界面
1.1 唯一父元素包裹
1.2 找可能发生变化的元素
本例中: 两个div根据条件不同二选一显示
1.3 找触发事件的元素
本例中:
点击登录的a元素时,切换为已登录状态
点击注销的a元素时,切换为未登录状态-->
<div id="app">
<!--已登录时显示-->
<!-- 记录当前用户是否登录-->
<div v-if="isLogin">
<h3>Welcome dingding <a href="javascript:;" @click="logout">注销</a></h3>
</div>
<!--未登录时显示-->
<div v-else>
<a href="javascript:;" @click="login">登录</a> |
<a href="javascript:;">注册</a>
</div>
</div>
<script>
//2. 创建new Vue()
new Vue({
el:"#app",
//3. 创建模型对象
//3.1 创建data对象
//本例中:因为界面上需要1个变量,所以
data:{
isLogin:false,//记录用户是否登录。开局,用户暂时未登录,所以初始值为false
},
//3.2 创建methods对象
//本例中:因为界面中需要2个函数,所以
methods:{
login(){
//让用户变成已登录状态
this.isLogin=true;
},
logout(){
//让用户变回未登录状态
this.isLogin=false;
}
}
})
</script>
</body>
</html>
运行结果: (4). v-else-if:
a. 什么是: 和v-if v-else配合来控制多个元素多选一显示的特殊指令
b. 如何:
<元素1 v-if="条件1">
<元素2 v-else-if="条件2">
... ...
<元素n v-else>
c. 原理: new Vue()扫描到v-if时,先执行=右边的条件1。
1). 如果条件1为true,则显示v-if所在的元素,删除之后所有v-else-if和v-else
2). 如果条件1为false,则先删除v-if所在的元素,依次判断v-else-if后的条件。只要有任何一个v-else-if条件满足,则只保留这一个v-else-if所在的元素,删除其余元素
3). 如果所有v-if 和v-else-if的条件都不满足,则删除所有v-if和v-else-if所在元素,只保留v-else
d. 示例: 根据pm25值不同,显示不同表情
7_v-else-if.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<img v-if="pm25<100" src="img/1.png" alt="">
<img v-else-if="pm25<200" src="img/2.png" alt="">
<img v-else-if="pm25<300" src="img/3.png" alt="">
<img v-else src="img/4.png" alt="">
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
pm25:160
}
})
</script>
</body>
</html>
运行结果:
(5). v-for:
a. 什么是: 专门根据一个数组的内容反复生成多个相同结构的HTML元素的特殊指令
b. 何时: 今后,只要希望根据一个数组中的元素内容,来生成相应个数的HTML元素,都要用v-for。
c. 如何: <要反复生成的元素 v-for="(元素值, 下标i) of 数组">
强调: of前的()中第一个变量必须接住值,第二个变量必须接住下标/属性名。变量名可以随便改,但是顺序改不了。
d. 原理: new Vue()只要扫描到v-for,就会自动遍历of后的数组中每个元素。每遍历一个元素,就自动返回元素的内容和下标,保存到of前的两个变量中。并且,每遍历一个元素, v-for都自动创建一个当前HTML元素的副本。遍历了数组中的几个元素,最终就会反复创建几个相同结构的HTML元素副本。
e. v-for还能遍历对象中每个属性:
1). 其实vue中的v-for统一了js中for of和for in的功能
2). 其实v-for="(元素值, 下标i) in 数组/对象"
3). 其实写in和写of完全一样!都是既能遍历索引数组,又能遍历对象中的属性。
f. VUE2的两个著名的坑:
1). 如果使用"数组[下标]=新值"方式来修改数组中某个位置的元素,则即使数组内容可以修改成功,那么页面也不会跟着自动变化
原因: vue中并没有给数组中的数字下标添加任何访问器属性,所以vue中所有数字下标,都是不受监控的!
临时解决: 所有对数组的修改,不要用下标来做。用数组类型提供的那些API函数来实现。
比如: 想修改数组中1位置的元素值为新值:
错误: 数组[1]=新值
正确: 数组.splice(1,1,新值)
从1位置删除1个元素
再将新值插入到1位置——完成替换
将来解决: 升级到VUE3,自动解决了.
2). 在运行时,为对象添加新属性,则新属性不会自动更新界面。
原因: VUE2的new Vue()只能对开局时对象中现有的属性自动添加访问器属性。而,将来在运行时,由程序动态添加的属性,都无法实时自动获得访问器属性。所以,又会出现不受监控的属性
解决: 只能升级VUE3
g. v-for的问题:
1). v-for很蠢,即使我们在程序中只修改了一个元素值,因为v-for无法区分页面上的HTML元素,所以,只能删除整个列表,重建整个列表。——效率低
2). 根本原因: v-for反复生成的多个HTML元素副本,没有差别!
3). 解决: vue规定,今后只要使用v-for,都必须为元素同时绑定:key属性,且属性值应该是一个不重复的下标或属性名。
4). 如何:
<元素 v-for="(元素值, 下标i) of 数组" :key="下标i">
5). 原理:
i. 今后,v-for每创建一个HTML元素副本,都会绑定一个key属性,属性值为数组中一个不重复的下标
ii. 今后,当更新数组中某一个元素时,v-for就可根据HTML元素上绑定的唯一的key属性值,只找到对应的一个HTML元素,修改其内容即可。不会更新列表——效率高!
6). 总结: v-for为什么必须带:key
为每个元素添加唯一标识,避免更新一个元素时重建整个列表.
h. 示例: 使用v-for遍历索引数组和对象
8_v-for.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<h3>遍历数组中每个元素</h3>
<ul>
<li v-for="(str,i) of arr" :key="i">
{{i+1}} - {{str}}
</li>
</ul>
<h3>遍历对象中每个属性</h3>
<ul>
<li v-for="(属性值, 属性名) of lilei" :key="属性名">{{属性名}} - {{属性值}}</li>
</ul>
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
arr:["亮亮","楠楠","东东"],
lilei:{
sname:"Li Lei",
sage:11,
class:"初一2班"
}
}
})
//1. vm.arr[1]="涛涛" //修改不成功
//2. vm.arr.splice(1,1,"涛涛") //成功
//3. vm.lilei.money=100 //没成功
</script>
</body>
</html>
运行结果:
遍历数组中每个元素
1 - 亮亮
2 - 楠楠
3 - 东东
遍历对象中每个属性
sname - Li Lei
sage - 11
class - 初一2班
i. 其实v-for也可以根据一个整数反复生成指定个数的HTML元素.
1). <元素 v-for="i of 整数" :key="i">
2). 原理: v-for会自动从1开始,连续数数,数到给定的整数结束。每数一个数,就自动创建当前HTML元素的一个副本。
3). 示例: 生成分页按钮
9_v-for_pages.html
![4.png](https://upload-images.jianshu.io/upload_images/22277500-58d42cbaae9910a2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="js/vue.js"></script>
<style>
ul{
list-style: none;
}
ul>li{
float:left;
width:40px;
height:40px;
text-align:center;
line-height:40px;
border:1px solid #555;
border-radius: 5px;
margin-left:5px;
}
ul>li:hover{
cursor:pointer;
background-color:lightskyblue;
color:#fff;
border:0;
}
</style>
</head>
<body>
<div id="app">
<ul>
<li v-for="i of pageCount" :key="i">{{i}}</li>
</ul>
</div>
<script>
var vm=new Vue({
el:"#app",
data:{
pageCount:10 //共6页
}
})
</script>
</body>
</html>
运行结果:
常见错误: Error compiling template : 模板编译错误
通常因为HTML中所写的HTML标签或绑定语法不符合vue的要求了!
进一步确定出错的位置:
沿控制台左侧向下找,跳过大片的HTML代码,找到一个很短的"-",这里标记的就是出错的位置!
总结:
1. MVVM: 界面View+模型Model+视图模型ViewModel
2. Vue绑定原理: 访问器属性+虚拟DOM树
变量被修改时: 访问器属性发出通知,虚拟DOM树扫描并仅更新受影响的元素
3. 虚拟DOM树优点:
(1). 小: 只包含可能变化的元素。
(2). 遍历查找快
(3). 修改效率高: 只修改受影响的元素。
(4). 避免重复编码: 已封装DOM增删改查代码
4. Vue功能3步:
(1). 先创建增强版的界面:
a. 整个界面必须包含在一个唯一的父元素下:
通常是<div id="app">
b. 可能变化的元素内容用{{自定义变量名}}标记
c. 触发事件的元素用@click="自定义处理函数名"标记
(2). 再创建new Vue()对象,其中el:指向new Vue()要监控的页面区域
(3). 在new Vue()对象内定义模型对象data和methods
a.界面所需的所有变量都放在data中
b.界面所需的所有事件处理函数都放在methods中
5. 总结: 绑定语法+13种指令
(1). 如果元素的内容需要随变量自动变化: {{}}
(2). 如果元素的属性值需要随变量自动变化: :
(3). 控制一个元素显示隐藏: v-show
(4). 控制两个元素二选一显示: v-if v-else
(5). 多个元素多选一显示: v-if v-else-if v-else
(6). 只要反复生成多个相同结构的元素组成列表时: v-for :key="唯一标识"