vue
第三方开发的,基于MVVM设计模式的,渐进式的,纯前端js框架
渐进式的:可以逐步在项目中使用vue的部分功能,可以轻松和其他技术混搭------强烈不建议
纯前端js框架:与后端node.js毫无关系。只靠浏览器就可以执行
以数据操作(增删改查)为主的项目,都可以用vue框架来实现。比如:电商、新闻、微博、知乎、协同办公、管理系统、官网。
框架和库的区别:库指的是工具的集合,我们可以选中其中某些来使用。eg:函数库 jquery
框架:可以帮我们自动化的完成很多重复性的任务。避免重复编码。
原生 浏览器自带的 dom
vue使用
官网:cn.vuejs.org
2种下载方式:
(1)只下载vue.js文件,引入到网页中。------适合于初学者入门使用(前端项目非常庞大,文件和文件夹结构复杂,不便于管理和项目通用。)
引入<script src="js/vue.js">
需要用的文件
链接:https://pan.baidu.com/s/1fAGaUUNMi4yuWW2-TxYgEg
提取码:gvg5
(2)脚手架:一套标准的文件夹和文件结构。(公司中)
优点;脚手架代码是vue官方提供的标准化的项目结构。今后如果所有公司都采用脚手架代码基础上进行开发,则每个公司的框架几乎一样!极其便于学习和分工协作。
vue版本:开发版:拥有完备的注释和代码结构,拥有见名知意的变量名。且拥有非常友好的错误提示。
生产版:去掉了所有注释和代码结构,极简化了变量名。且去掉了友好的错误提示!
vuejs文件的使用
1.页面引用js文件
2.使用基本结构
案列:点击按钮数字增加或减少,vue/jquery的不同写法
不要忘记引用他们的js文件
<!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">
<script src="js/jquery-1.11.3.js"></script>
<title>Document</title>
</head>
<body>
<button>-</button><span>0</span><button>+</button>
<script>
//DOM
//先做+
//1.查询触发事件的元素
//本例中:查找内容中包含+的按钮元素
// var $button=$("#button");
$("button:contains(+)") .click(function(){
//3.查找要修改的元素
//本例中:要修改当前按钮的前一个兄弟span的内容
var $span=$(this).prev();
//4.修改元素
//4.1先取出span的内容,转为整数
var n=parseInt($span.html());
//4.2将n+1
n++;
//4.3再放回去
$span.html(n);
})
//做-
//1.查询触发事件的元素
//本例中:查找内容中包含-的按钮元素
$("button:contains(-)")
//2.绑定事件处理函数
.click(function(){
//3.查找要修改的元素
//本例中:要修改当前按钮的后一个兄弟span的内容
var $span=$(this).next();
//4.修改元素
//4.1先取出span的内容,转为整数
var n=parseInt($span.html());
//4.2如果n>0减一
if(n>0){
n--;
}
//4.3再放回去
$span.html(n);
})
</script>
</body>
</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>
<!-- 1.现做界面 -->
<!--1.1 整个界面必须用唯一的父元素包裹
<div id="app"></div> -->
<!-- 1.2 找界面中哪里将来那些功能变化,用专门的语法“{{自定义变量}}”标记出来--占位-->
<!-- 1.3 找界面中哪里可能触发事件,在元素开始标签中,用@事件名=“自定义处理函数名”方式标记/占位 -->
<!-- 2.创建一个new Vue()对象监视页面中id为app的div区域 -->
<!-- 3.创建模型对象:分别保存页面中所需的所有变量 和事件处理函数的专用对象 -->
<div id="app">
<!-- <button>-</button><span>0</span><button>+</button> -->
<!-- span的内容会变化 -->
<!-- 单击-/+号按钮,会执行操作 -->
<button @click="minus">-</button><span>{{n}}</span><button @click="add">+</button>
</div>
<script>
// 创建一个new Vue()对象监视页面中id为app的div区域
new Vue({
//el element id 选择器
el:"#app", //让当前new Vue对象监视id为app的元素及其子元素
//data{}对象,专门用来保存页面中所需的所有变量和初始值
data:{
n:0 //本例中,因为页面中只需要一个变量n,所有n:0
},
//3.2 methods{}对象,专门用来保存页面中所需的所有事件处理函数
methods:{
//因为页面中需要两个单击事件处理函数,这里是箭头函数的简化
//add:function(){}
add(){
//在methods中的函数中,只需要关心如何操作变量值,不要考虑任何页面元素相关的事情
//但是,methods中的方法,想操作data中的变量,必须加this
this.n++;
},
minus(){
if(this.n>0){
this.n--;
}
}
}
})
</script>
</body>
</html>
MVVM
旧的前端代码划分为3部分
HTML:定义网页的内容和结构
CSS:定义网页的样式
js:为页面添加交互行为
因为html/css太弱了,不支持变量,修改变量需要js来实现。因此,导致js包含了大量重复的代码。
为了解决这个问题,出现了MVVM.
MVVM设计模式
对前端三大内容进行了重新划分
界面 view
包含了html+css,它支持变量、分支、循环等程序必要的要素
模型对象 Model
专门为界面保存所需的变量和函数的特殊对象。
ViewModel对象
专门负责将界面和模型对象绑定起来。
它可以自动将模型对象中的变量值和函数,送到界面上所需的位置
它能监视程序中变量的变化,只要变量值发生变化,它自动保持界面上显示的值与程序中的变量值始终一致。
Vue的绑定原理
vue框架是如何实现mvvm设计模式的
简单的说:就是访问器属性set + 虚拟dom树
(1).new Vue()创建对象时,先将data对象引入到new Vue()对象中来。
a.将data中的实际变量隐藏起来
b.自动为data中每个变量请保镖(访问器属性)。访问器属性定义在data外部,直接隶属于new Vue对象。
c.每个变量的访问器属性都包含了两个函数:
get()函数专门负责读取隐藏的实际变量值,返回到外部
set()函数专门负责将外部修改的新值传递到隐藏的实际变量上。
d.结果:将来new Vue()使用任何变量,其实使用的都不是原始的变量,都是访问器属性替身变量而已。
e.引入methods对象,但是会将methods对象打散。结果,原来包含在methods中的方法,都泄露出来,直接隶属于new Vue()
f.结果:今后只要在methods中的方法中先使用data中的变量必须加this
(2).在首次加载页面时,new Vue()会扫描界面中所有可能发生变化的元素,创建虚拟DOM树。
什么是虚拟dom树:仅仅保存可能变化的元素的简化版Dom树。
原理如下:
1.在new Vue()中每个变量的访问器属性的set()方法内,都内置了一个通知函数。
2.将来只要在vue对象内修改了任何一个变量,都会自动触发set()方法调用。
不但将新值更新到隐藏的变量中
而且还会自动调用通知函数,通知虚拟Dom树,那个变量发生变化
3.虚拟dom开始遍历自己内部的所有元素,查看哪些元素受本次变量修改的影响
4.虚拟dom树会利用早已提前封装好的Dom增删改查操作,来修改个别受影响的元素。
![](https://i-blog.csdnimg.cn/blog_migrate/72c225cabaa27d0bcf4eb927593f6ad8.png)
虚拟dom树的优点
小:只包含可能变化的个别元素
查找快
避免大量重复的编码:已经提前封装好增删改查的操作
修改效率高:只修改个别受影响的元素
绑定语法
又叫插值语法 interpolation
定义:专门在html元素内容各种插入变量的特殊语法
何时用:只要一个元素的内容可能睡程序变化,都要用绑定语法标记
格式:
html js html
界面中:<元素>xxxx{{自定义变量名}}</元素>
new Vue()中的data:{}里,要定义页面中所需的所有变量。
结果:首次加载页面时,new Vue()会把data中变量的初始值,替换到界面中{{}}所在的位置
只要程序中的变量值发生改变,new Vue()会自动更新界面中{{}}位置的显示内容
{{}}中可以放什么
它的要求和ES6中模板字符串里${}的要求完全一样
可以放:变量、三目、算术计算、有返回值的方法调用、创建对象、访问数组下标,一切有返回值的js表达式
不可以放:分支、循环、没有返回值的表达式
小练习
![](https://i-blog.csdnimg.cn/blog_migrate/7e96dc6113c0c43d9948f61d12f89acb.png)
![](https://i-blog.csdnimg.cn/blog_migrate/7a9cacc8f18177184e057861961faa6e.png)
<!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>欢迎,{{uname}}</h3>
<h3>性别:{{sex==1?"男":"女"}}</h3>
<h3>小计:¥{{price*count.toFixed(2)}}</h3>
<h3>下单时间:{{new Date(orderTime).toLocaleString()}}</h3>
<h3>今天星期{{week[new Date().getDay()]}}</h3>
</div>
<script>
new Vue({
el:"#app",
data:{
uname:"xiaoxiao",
sex:1,
count:5,
price:12.5,
orderTime:1623155153358,
week:["日","一","二","三","四","五","六"]
}
})
</script>
</body>
</html>
指令 directive-----13个
定义:为html元素添加新功能的特殊的属性
何时用:希望为html元素添加程序中才有的分支、循环等功能时,都用指令
{{}}
元素的内容随着程序变化
之后会把这块补齐,虽然前面有
v-bind
元素的属性值随着程序自动变化,用:代替{{}},这里:承担了{{}}的功能,它也是js语法
格式:<元素 v-bind:属性名=“变量或js表达式”> ------原版
<元素 :属性名="变量或js表达式"> -------简化版
练习: 根据空气质量显示不同的表情
<!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>今天的空气质量:</h3>
<!-- 需求:pm25<100 1.png,pm25<200 2.png,pm25<300 3.png,其他4.png-->
<!-- <img src="img/1.png"> -->
<img :src="pm25<100?'img/1.png':pm25<200?'img/2.png':pm25<300?'img/3.png':'img/4.png'">
</div>
<script>
new Vue({
el:"#app",
data:{
//pm25后面的数值不同,图片也不同
pm25:200
}
})
</script>
</body>
</html>
v-show
定义:专门控制一个元素显示隐藏的指令
何时用:只要希望用程序控制一个元素显示隐藏时
格式:<元素 v-show="变量或条件表达式">
原理:只要new Vue()扫描到v-show所在的元素,就先计算“”中的变量或条件·表达式。
a.如果条件为true,当前元素正常显示。
b.如果条件为false,new Vue()自动给当前元素加display:none,让原宿1隐藏。
小练习
点击按钮,出现一个小方框
<!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>
<style>
#pop{
position:fixed;
top:20%;
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>
<!--
寻找哪里可能随程序变化
本例中: div的显示隐藏状态随程序自动变化,所以用v-show标记出来。
寻找哪里可能触发事件
本例中: 点button,会让div显示;点a,让div隐藏 -->
<div id="app">
<button @click="show">click me</button>
<div id="pop" v-show="isShow">
<a href="javascript:;" @click="hide">x</a>
</div>
</div>
<script>
new Vue({
el:"#app",
//3.创建模型对象
//3.1 创建data对象,保存所有界面中所需要的变量
//本例中,界面只需要一个isshow变量来标记div是否显示
data:{
isShow:false //开局,div默认不显示
},
//3.2创建methods对象,保存界面所需的所有事件处理函数
methods:{
show(){//事件处理函数中,通过修改data中的变量值,来遥控界面中的变化
this.isShow=true;
},
hide(){
this.isShow=false;
}
}
})
</script>
</body>
</html>
v-if v-else
定义:专门控制两个元素二选一显示的指令
何时用:只要控制两个元素二选一显示时都用v-if v-else
格式:
<元素1 v-if=“变量或判断条件”>
<元素2 v-else>
注意:v-if v-else两个元素必须紧挨着写!之间不能插入其他元素
v-else和在程序中的else一样,之后不需要写任何条件。
原理:当new Vue()扫描到v-if时,会先判断v-if后的条件是否为true.
如果v-if后的条件为true,则保留v-if所在的元素,删除v-else所在元素
如果v-if后的条件为false,则删除v-if所在的元素,只保留v-else所在元素
v-show和v-if的差别
v-show,用display方式隐藏元素----不改变DOM树结构-----效率稍微高
v-if,是通过删除元素方式隐藏元素---改变DOM树结构---效率稍微低
问题:v-else被删除后,怎么又可能回到页面
页面刚加载时,new Vue()早就把v-if和v-else两个元素都扫描到,永久保存在虚拟Dom树中。即使将来删除,删除的也是页面上真实Dom中的元素,不会删除虚拟Dom树中的元素的。每次,会根据条件的不同,指派虚拟Dom树中的V-if 或v-else重新回到页面上。
小练习
点击登录,出现welcome dingding 注销,点击注销,返回开始页面
<!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">
<!-- 点登录,将状态改为已登录;点注销,将状态改为未登录 -->
<!-- 登录显示 -->
<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>
new Vue({
el:"#app",
//3创建模型对象
//3.1创建data对象,保存页面所需变量
//本例中:因为界面上只需要一个变量isLogin
data:{
isLogin:false
},
//3.2创建methods对象,保存页面所需事件处理函数
//本例中:因为界面上需要两个事件处理函数
methods:{
login(){
this.isLogin=true
},
logout(){
this.isLogin=false
}
}
})
</script>
</body>
</html>
v-else-if
定义:v-if和v-else联合使用,共同控制多个元素多选一显示的特殊指令
何时用:只要控制多个元素多选一显示
格式:<元素1 v-if="条件1">
<元素2 v-else-if="条件2">
.......
<元素n v-else>
注意:v-if 和v-else-if 和v-else之间必须紧挨着写,不能插入其他元素。
原理:new Vue()扫描到v-if,先判断v-if的条件
如果v-if条件满足,就保留v-if所在元素。,删除其余v-else-if和v-else所在的元素.
如果v-if条件不满足,就判断v-else-if。那个v-else-if 条件满足,就只保留哪个v-else-if所在元素。删除其余v-if、v-else-if、v-else元素。
如果v-if和v-else-if条件都不满足,则删除所有v-if和v-else-if,只保留v-else所在元素。
小练习
根据指数不同显示图片不同
注意:不要忘记引用js vue文件
<!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">
<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>
new Vue({
el:"#app",
data:{
pm25:120
}
})
</script>
</body>
</html>
v-for
没懂诶,例子中的name和i哪里来的?
定义:专门反复生成一组连续的结构相同的元素的特殊指令
何时用:只要在页面中需要连续反复生成多个结构相同的元素时
格式:<要反复生成的元素 v-for="(元素,下标i) of/in 数组">
注意:v-for一定要写在反复生成的元素上,不要写在父元素上。
按照严格的规定,of前的两个变量必须包裹在()中
vue中的v-for统一了js中的for of和for in,所以,用of/in都可以,效果是一样的.
v-for即可遍历索引数组,又可遍历对象
of/in前的两个变量,每个变量都可随意修改,但是顺序不能变,第一个变量接值,第二个变量接下标或属性
原理:new Vue()扫描到v-for时,就会自动遍历of或in后的数组或对象中每个成员
每遍历数组或对象中的一个成员,就会创建当前元素的一个副本。
同时,还会将当前成员的值,赋值给of/in前的第一个变量,再将当前成员的下标或属性名,赋值给of/in前的第二个变量
of/in前的变量,虽然没有定义在data中,但是依然可以用于当前元素及其子元素中的绑定或指令中。
坑:用下标修改数组中的元素值,虽然数组中可以修改,但是页面中不会自动跟着变!
原因:因为索引数组的下标是数字。数字下标都是不受监视的。
解决:虽然索引数组的下标不受监控,但是数组家所有的函数都被监控了!所以,将来只想通过下标修改数组元素值时,都要改用函数来修改。
eg:arr[0]=“小月月” 错误
arr.splice(0,1,"小月月") 正确
问题:哪怕只修改了数组中一个元素值,v-for很蠢,只会删除旧的所有元素副本,重建整个列表。-------效率极低!
原因:v-for默认生成的元素副本,除了内容不同之外,所有副本元素是完全一样的。v-for无法区分哪个元素对应数组中哪个成员。所以,每次数组修改时,被迫重建整个列表
解决:只要使用v-for,同时必须绑定:key属性,且绑定给:key属性的变量的值必须是唯一的不重复的!且:key不能改名。
原理:key属性为每个新创建的元素副本都添加了一个唯一标识(虽然看不见,但客观存在)。但数组中某个下标位置的元素被改变时,v-for就可通过下标找到对应key值的一个元素副本,只修改这个元素的内容。其余元素保持不变!不用重建整个列表。--------效率大大提高!
总结:v-for为什么必须绑定:key
为每个元素副本添加唯一标识,当修改时,只修改一个元素副本,为了防止v-for重建整个列表。-------提高v-for的加载效率
v-for还会数数:
a.<元素 v-for="i of 整数”>
结果:从v-for从1开水!连续数整数,直到of后的整数结束。每数一个数:
将本次数的数给of前的变量i
而且会创建当前元素的一个副本
eg:<元素 v-for="i of 5">{{}}元素
结果:<元素>1</元素><元素>2</元素><元素>3</元素><元素>4</元素><元素>5</元素>
小练习
<!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">
<ul>
<li v-for="(name,i) of arr">第{{i+1}}阶段:{{name}}</li>
</ul>
<hr/>
<!-- for in循环知识点 -->
<li v-for="(value,key) of lilei">{{key}}:{{value}}</li>
</div>
<script>
new Vue({
el:"#app",
data:{
arr:["lili","zhaozhao","wangwang"],
lilei:{
sname:"Li lei",
sage:11,
className:"初一二班"
}
}
})
</script>
</body>
</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>
<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>
new Vue({
el:"#app",
data:{
pageCount:6
}
})
</script>
</body>
</html>
V-On
定义:专门绑定事件处理函数的指令
何时用:只要为元素绑定事件处理函数,都要用v-on
格式:<元素 v-on:事件名=“事件处理函数(参数)”>------原版
<元素 @事件名=“事件处理函数(参数)”>--------简化版
如果事件处理函数不需要传实参值,则可以省略()
注意:页面上需要几个事件处理函数,在methods中就要提供几个事件处理函数。
事件处理函数传参:
如何传参 <元素 @事件名=“事件处理函数(实参值1,.....)”>
methods:{
事件处理函数(形参1,....)
......
}
}
获取事件对象
<元素 @事件名=“事件处理函数”>
methods:{
//当事件发生时,浏览器自动创建event对象
事件处理函数(e){
e 就会自动获得浏览器自动创建的event对象
}
}
注意:如果想获得事件对象,则html中绑定时,一定不要写(),加()表示不传任何
参数的意思,vue一看到(),也就不会自动给你传事件对象参数了。
形参e获得的事件对象和DOM的事件对象完全一样。
问题:如果想传自定义实参,就无法获得事件对象e。如果想获得事件对象e,就不能传自定义实参
解决:如何既获得事件对象,又传入自定义实参值
在html中,vue已经提前封装好了一个关键字---$event.它可以在事件发生时自动提前获得事件对象,并保存起来。
当事件发生时,浏览器自动创建事件event,先给
html: <元素 @事件名=“事件处理函数($event,其他实参值,....)”>
methods:{
事件处理函数(e,形参,...){
}
}
注意:vue中凡是以$开头的词都是关键字,不可改名
html中$event和其他实参值的顺序,可以调换位置,只要实参值和methods中的形参列表对应就好。
小练习
点谁谁呵呵
<!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">
<img src="img/1.png" @click="say('微笑')">
<img src="img/2.png" @click="say('撇嘴')" >
</div>
<script>
new Vue({
el:"#app",
methods:{
say(name){
console.log(`${name}呵呵!`);
}
}
})
</script>
</body>
</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">
<img src="img/1.png" @click="say">
<img src="img/2.png" @click="say" >
</div>
<script>
new Vue({
el:"#app",
methods:{
say(e){
console.log(`${
e.offsetY<30?"上脸":e.offsetY<70?"下脸":"脸"
}呵呵!`);
}
}
})
</script>
</body>
</html>
报错总结
Error compiling template:界面中绑定语法或指令出错了
Interpolation inside attributes has been remove.
在属性里的插值语法已经被移除了。
invalid expression: Unexpected identifier in 无效表达式,符号错了
Raw expression 原始表达式
![](https://i-blog.csdnimg.cn/blog_migrate/97cbde67eab09c4a487674c5a2b17a38.jpeg)