Vue的使用
一、安装
对于新手来说,强烈建议大家使用<script>引入:
二、 引入vue.js文件
我们能发现,引入vue.js文件之后,Vue被注册为一个全局的变量,它是一个构造函数。
三、使用Vue实例化对象
<div id="app"> <!--插值语法--> <h3>{{msg}}</h3> <h3>{{1+1}}</h3> <h3>{{1>2?"真的":"假的"}}</h3> <div v-if="show">哈哈</div> <button v-on:click ="clickHandler">切换</button> </div> <script src="vue.js"></script> <script> //vue的实例化对象 //指令系统 v-* var app = new Vue({ el:"#app", data:{ msg:"今天学习Vue", msg2:"今天学习Vue2", show:false }, methods:{ clickHandler(){ this.show=!this.show //通过按钮实现反转实现显示哈哈与消失哈哈 } } }); console.log(app); console.log(app.$el); console.log(app.$data.msg); //今天学习Vue console.log(app.msg) //今天学习Vue </script>
ok,我们已经简单的创建了第一个vue应用。渲染的数据的方式我们也叫声明式的渲染。现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。我们要怎么确认呢?打开你的浏览器的 JavaScript 控制台 (就在这个页面打开),并修改 app.msg
的值,你将看到上例相应地更新。
在上面案例中,我们学到了,{{ }}插值的语法。
{{}}插值,不仅可以插变量,只要你能想到的插入都可以,if-else不可以啊!!!
最后:
指令集
所谓指令系统,大家可以联想咱们的cmd命令行工具,只要我输入一条正确的指令,系统就开始干活了。
在vue中,指令系统,设置一些命令之后,来操作我们的数据属性,并展示到我们的DOM上。
一、V-IF指令:
<div id="app"> <!--插值语法--> <h3>{{msg}}</h3> <h3>{{1+1}}</h3> <h3>{{1>2?"真的":"假的"}}</h3> <div v-if="show">哈哈</div> </div> <script src="vue.js"></script> <script> //vue的实例化对象 //指令系统 v-* var app = new Vue({ el:"#app", data:{ msg:"今天学习Vue", msg2:"今天学习Vue2", show:false } </script>
这个v-if如果是true,那么就显示,如果是false,那么就不显示。
注意:show变量,是数据属性中存储的值。要么真(true)要么假(false)。该属性值为true的时候,p标签显示,反之则不显示。
二、V-ON指令:
<div id="app"> <!--插值语法--> <h3>{{msg}}</h3> <h3>{{1+1}}</h3> <h3>{{1>2?"真的":"假的"}}</h3> <div v-if="show">哈哈</div>
<div v-else>呵呵</div> //如果哈哈显示,呵呵就不显示,如果哈哈不显示,呵呵就显示。 相当于if-else
<button v-on:click ="clickHandler">切换</button> </div> <script src="vue.js"></script> <script> //vue的实例化对象 //指令系统 v-* var app = new Vue({ el:"#app", data:{ msg:"今天学习Vue", msg2:"今天学习Vue2", show:false }, methods:{ clickHandler(){ this.show=!this.show } } }); console.log(app); console.log(app.$el); console.log(app.$data.msg); //今天学习Vue console.log(app.msg) //今天学习Vue </script>
可以给button绑定一个函数,然后vue对象中写一个method,使用的是单体模式,这里的this指的是当前Vue对象,而不是window对象。这样可以
实现div里面哈哈的显示和隐藏。
另外还有v-else-if块,它是2.1.0新增的。
<div v-if="type === 'thunder' > 打雷 </div> <div v-else-if="type === 'rain'> 下雨 </div> <div v-else> 雷阵雨 </div>
如果type是thunder的话,那么显示打雷,如果是rain,表示下雨,如果是其他的显示雷阵雨。 (type是在vue对象的data里定义的)。
二、V-SHOW指令:
<div id="app"> <!--插值语法--> <h3>{{msg}}</h3> <h3>{{1+1}}</h3> <h3>{{1>2?"真的":"假的"}}</h3> <div v-if="show">哈哈</div> <button v-on:click ="clickHandler">切换</button> <h3 v-show="isShow">我是一个三级标题</h3> </div> <script src="vue.js"></script> <script> //vue的实例化对象 //指令系统 v-* var app = new Vue({ el:"#app", data:{ msg:"今天学习Vue", msg2:"今天学习Vue2", show:false, isShow:false } </script>
这里的v-show如果是false,不显示,如果是true则显示。但是和v-if还是有区别的
这里的show是加了一个属性,而v-if是直接DOM就不存在了。
注意:v-show不支持v-else块
三、V-IF VS V-SHOW对比:
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
四、V-bind:
操作元素的 class 列表和内联样式是数据绑定的一个常见需求。因为它们都是属性。所以我们可以用 v-bind
处理它们:只需要通过表达式计算出字符串结果即可。不过,字符串拼接麻烦且易错。因此,在将 v-bind
用于 class
和 style
时,Vue.js 做了专门的增强。表达式结果的类型除了字符串之外,还可以是对象或数组。
css样式:
.box1{
100px;
height: 100px;
background-color: red;
}
.box2{
100px;
height: 100px;
background-color: green;
}
<div id="app"> <!--插值语法--> <h3>{{msg}}</h3> <h3>{{1+1}}</h3> <h3>{{1>2?"真的":"假的"}}</h3> <div v-if="show">哈哈</div> <button v-on:click ="clickHandler">切换</button> <!--下面是on的简便写法--> <button @click ="clickHandler">切换</button> <h3 v-show="isShow" v-bind:title="title">我是一个三级标题</h3> //v-show如果是true就显示,如果是false就不显示
//这里的v-bind的title='title'意思就是取到data里面的title,下面的title是哈哈哈.
<img v-bind:src="Src" > <!--下面是bind的简便写法--> <img :src="Src" > <div v-bind:title="time"></div> //这里出来的效果就是取到data里面反引号拼接的字符串,取到当地事件放到title上。 <div class="box" v-bind:class='{box2:isgreen}'></div> <button v-on:click="changecolor">切换颜色</button> </div> <script src="vue.js"></script> <script> //vue的实例化对象 //指令系统 v-* var app = new Vue({ el:"#app", data:{ msg:"今天学习Vue", msg2:"今天学习Vue2", show:false, isShow:true, title:"哈哈哈", Src:"1.png", time:`页面加载于${new Date().toLocaleString()}`, isgreen:true }, methods:{ clickHandler(){ this.show=!this.show }, changecolor(){ this.isgreen=!this.isgreen } } }); </script>
对象语法
我们可以传给 v-bind:class
一个对象,以动态地切换 class:
...
data:{
isRed:true
}
<div v-bind:class='{box1:isRed}'></div>
具体实现在上面的代码中,给div绑定了一个对象
v-bind:class='{box2:isgreen}',目前isgreen是false,box2属性不显示,而当给按钮绑定了事件后,
<div class="box" v-bind:class='{box2:isgreen}'></div> <button v-on:click="changecolor">切换颜色</button>
点击按钮,将isgreen变成false。那么去掉了box2的属性。
changecolor(){
this.isgreen=!this.isgreen
}
数组语法
我们可以把一个数组传给v-bind:class,以应用一个 class 列表:
<div v-bind:class="[activeClass, errorClass]"></div>
data: { activeClass: 'active', errorClass: 'text-danger' }
渲染为:
<div class="active text-danger"></div>
如果你也想根据条件切换列表中的 class,可以用三元表达式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
这样写将始终添加 errorClass
,但是只有在 isActive
是 true时才添加 activeClass
。
不过,当有多个条件 class 时这样写有些繁琐。所以在数组语法中也可以使用对象语法
<div v-bind:class="[{ active: isActive }, errorClass]"></div
事件处理:
可以用 v-on
指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
核心思想:事件驱动视图。
首先肯定是渲染{{count}},然后在data中找到了count为0,点击触发绑定的点击事件,执行运算,得到count=1,然后把这个1实时渲染到按钮上。
1 <div id='app'> 2 <button v-on:click = 'count+=1'>加{{count}}</button> 3 <p>点了{{count}}次</p> 4 </div>
1 var app = new Vue({ 2 el:'#app', 3 data:{ 4 count:0 5 } 6 })
结果为:当我点击的按钮的时候,下面p标签的数据也会发生变化,同时button的文字也会发生变化。
事件处理方法
然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在 v-on
指令中是不可行的。因此 v-on
还可以接收一个需要调用的方法名称
1 <div id='app'> 2 <button v-on:click = 'countClick'>加{{count}}</button> 3 <p>点了{{count}}次</p> 4 </div>
var app = new Vue({ el:'#app', data:{ count:0 }, methods:{ countClick(){ this.count+=1; //在这里写逻辑,实现的功能和上面的是一模一样。 } } })
在这里多补充一点:v-bind可以简写为:、v-on: 可以简写@
为什么在HTML中监听事件?
你可能注意到这种事件监听的方式违背了关注点分离 (separation of concern) 这个长期以来的优良传统。但不必担心,因为所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的 ViewModel 上,它不会导致任何维护上的困难。实际上,使用 v-on
有几个好处:
-
扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。
-
因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。
-
当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何自己清理它们。
列表渲染
一个数组列表的v-for
用v-for把一个数组对应为一组的元素。
我们用 v-for
指令根据一组数组的选项列表进行渲染。v-for
指令需要使用 item in items
形式的特殊语法,items
是源数据数组并且 item
是数组元素迭代的别名。
另外:v-for
还支持一个可选的第二个参数为当前项的索引。
<div> <ul> <img v-bind:src="currentsrc" v-on:mouseenter="closetimer" v-on:mouseleave="opentimer"> <li v-for="(item,i) in imgarr" v-on:click="currenthandler(item)">{{i+1}}</li> //这里的item就是每一个数据,i就是索引(不是ID) </ul> <button v-on:click="nextimg">下一张</button> </div>
在data中写好这个列表
var app = new Vue({
el:"#app",
data:{
msg:"今天学习Vue",
msg2:"今天学习Vue2",
show:false,
isShow:true,
title:"哈哈哈",
Src:"1.png",
time:`页面加载于${new Date().toLocaleString()}`,
isgreen:true,
count:0,
imgarr:[
{id:1,src:'1.jpg'},
{id:2,src:'2.jpg'},
{id:3,src:'3.jpg'},
{id:4,src:'4.jpg'},
],
一个对象的v-for
你也可以用 v-for
通过一个对象的属性来迭代。
最后是一个Vue实现轮播图的小实例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .box{ background-color: red; width: 100px; height: 100px; } .box2{ background-color: green; } </style> </head> <body> <div id="app"> <!--插值语法--> <h3>{{msg}}</h3> <h3>{{1+1}}</h3> <h3>{{1>2?"真的":"假的"}}</h3> <div v-if="show">哈哈</div> <button v-on:click ="clickHandler">切换</button> <!--下面是on的简便写法--> <button @click ="clickHandler">切换</button> <h3 v-show="isShow" v-bind:title="title">我是一个三级标题</h3> <img v-bind:src="Src" > <!--下面是bind的简便写法--> <img :src="Src" > <div v-bind:title="time"></div> <div class="box" v-bind:class='{box2:isgreen}'></div> <button v-on:click="changecolor">切换颜色</button> <button v-on:click="count+=1">加{{count}}</button>
//这个div就是用来做轮播图的
<div> <ul>
//img绑定一个路径,绑定一个鼠标悬停状态事件,一个鼠标离开事件 <img v-bind:src="currentsrc" v-on:mouseenter="closetimer" v-on:mouseleave="opentimer"> //循环data的列表,将索引放到li内。
<li v-for="(item,i) in imgarr" v-on:click="currenthandler(item)">{{i+1}}</li> </ul> <button v-on:click="nextimg">下一张</button> </div> </div> <script src="vue.js"></script> <script> //vue的实例化对象 //指令系统 v-* var app = new Vue({ el:"#app", data:{ msg:"今天学习Vue", msg2:"今天学习Vue2", show:false, isShow:true, title:"哈哈哈", Src:"1.png", time:`页面加载于${new Date().toLocaleString()}`, isgreen:true, count:0, imgarr:[ {id:1,src:'1.jpg'}, {id:2,src:'2.jpg'}, {id:3,src:'3.jpg'}, {id:4,src:'4.jpg'}, ], currentsrc:'1.jpg', currentIndex:0, timer:null, },
//这里这个方法是在data下面,方法上面的一个特定的方法。名字固定。加一个定时器,是图片播放,2S执行一下下一张图的事件。 created(){ this.timer=setInterval(this.nextimg,2000) }, methods:{ clickHandler(){ this.show=!this.show }, changecolor(){ this.isgreen=!this.isgreen },
//上面通过传参拿到item,然后当前src是item的src,这样上面img图片通过data拿到的也就是currentsrc(更新以后的) currenthandler(item){ this.currentsrc=item.src },
//下一张图片的时间,默认索引为0,点一下索引+1,然后把src也顺便修改了。判定条件就是索引超过长度,让他成为第一张图 nextimg(){ if(this.currentIndex==this.imgarr.length-1){ this.currentIndex=-1 } this.currentIndex++; this.currentsrc=this.imgarr[this.currentIndex].src },
//关闭定时器 closetimer(){ clearInterval(this.timer) },
//鼠标离开后继续开启定时器。 opentimer(){ this.timer=setInterval(this.nextimg,2000) } } }); </script> </body> </html>
v-html指令:
比如在data中有
str:"<p>嘿嘿嘿</p>"
想要把它渲染到div中的话不能使用插值的方法。
<div v-html="str"></div>
而是使用v-html
计算属性:
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:
<div> {{ message.split('').reverse().join('') }} </div>
在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 msg
的翻转字符串。当你想要在模板中多次引用此处的翻转字符串时,就会更加难以处理。
所以,对于任何复杂逻辑,你都应当使用计算属性。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div id="computed"> <div>{{reverseStr}}</div> <button v-on:click='Handler'>修改</button> </div> <script src="vue.js"></script> <script> var com = new Vue({ el:"#computed", data:{ msg:"hello world" }, methods:{ Handler(){ this.msg = 'hello luffy'; } }, computed:{ //计算数据属性 watch监听 (一旦上面执行,那么这里会立马监听到修改的值,然后反转。) // reverseStr(){ // return this.msg.split('').reverse().join(''); // } reverseStr:{ set:function () { }, get:function () { return this.msg.split('').reverse().join(''); } } } }) </script> </body> </html>
当我点击按钮的时候更改了当前的数据,同时div内容随时改变。
为什么会这样呢?
因为Vue知道com.currentMsg依赖与com.msg,因此当com.msg发生改变时,所有依赖com.currentMsg的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系。:计算属性的getter函数是没有副作用的,这使它更易于测试和理解。
同样的上面操作,我们不用computed声明的计算属性方法,而仅仅通过methods中声明的方法也能完成上面的效果,那么为什么又要使用computed方法呢?
因为计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要msg还没有发生变化,多次访问currentMsg计算属性会立刻返回之前计算的结果,而不比再次执行函数。同样的。每当触发重新渲染时,调用方法将总会执行函数。
我们为什么需要缓存?假设我们有一个性能开销比较大的的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。
更好的理解这个计算属性,可以通过下面的双向绑定的原理来理解。
表单输入绑定:
vue的核心:声明式的指令和数据的双向绑定。
那么声明式的指令,已经给大家介绍完了。接下来我们来研究一下什么是数据的双向绑定?
另外,大家一定要知道vue的设计模式:MVVM
M是Model的简写,V是View的简写,VM就是ViewModel。
单项绑定和双向绑定的区别:
单向绑定非常简单,就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新。
有单向绑定,就有双向绑定。
如果用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。
什么情况下用户可以更新View呢?填写表单就是一个最直接的例子。当用户填写表单时,View的状态就被更新了,如果此时MVVM框架可以自动更新Model的状态,那就相当于我们把Model和View做了双向绑定。
其实单项数据也有双向绑定的意思,不过页面变动后数据的变化不会发生自动更新。
我们可以这样认为:双向数据绑定=单向数据绑定+UI事件监听。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form id="computed"> <input type="text" v-model="msg"> <h3>{{msg}}</h3> </form> <script src="vue.js"></script> <script> var com = new Vue({ el:"#computed", data:{ msg:"123" }, methods: {}, computed:{ } }) </script> </body> </html>
效果显示,当我们在input输入框中输入内容的时候,下面p标签同步显示内容。这就是最典型的双向数据绑定的例子。vue里使用v-model实现此想法。
通过官网知道v-mode指令是v-bind:vlaue 和v-on:input的结合体。
下面就是这个内部实现机制:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form id="computed"> <!--<div>{{reverseStr}}</div>--> <!--<button v-on:click='Handler'>修改</button>--> <input type="text" v-bind:value="msg" @input="msgChange"> <h3>{{getValue}}</h3> </form> <script src="vue.js"></script> <script> var com = new Vue({ el: "#computed", data: { msg: "123" }, methods: { msgChange(e){ this.getValue = e.target.value; } }, computed: { getValue:{ set:function (newValue) { this.msg=newValue; }, get:function () { return this.msg } } } }) </script> </body> </html>
V-model:
v-model
指令在表单 <input>
及 <textarea>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但 v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
v-model只适用在表单控件中
比如:表单文本、多行文本、复选框、单选按钮、多选按钮、选择框。