本文是我在学习vue的过程中记录学习的点点滴滴,仅仅为了学完之后巩固一下,日后忘记了也可以方便快速的复习。
vue中常用的那些指令介绍
前言
今天主要学习的是关于vue中那些常用的一些指令的介绍,包括v-text、v-html、v-model、v-cloak、v-bind、 v-on、v-if、v-show、v-for
一、什么是指令
指令 (Directives) 是带有 v- 前缀的特殊 attribute【vue 指令都以 v-开头】。指令 attribute 的值预期是单个 JavaScript 表达式 (v-for是例外情况)
二、指令系统
2.1、v-text、v-html
{
{msg}}可以用 v-text 指令替代
以下两种效果一致,都是显示data中的msg的变量值,
与{
{ }}语法基一样但不完全相同:
<h1>{
{msg}}</h1>
<h1 v-text="msg"></h1>
v-text只会识别其中的字符串,并不会解析其中的标签
如果msg中的数据是一个链接:
msg:'<a href="http://www.baidu.com">百度</a>
<h1 v-text="msg"></h1>
显示结果:
2.2、v-html
v-html和v-text一样都是显示文本内容,也可以替代{
{}},但是v-html会解析data中msg中的标签
例如我们来对v-text和v-html进行比较
<h1>{
{msg}}</h1>
<h1 v-text="msg"></h1>
<h1 v-html="msg"></h1>
运行结果:
2.3、v-text、v-html、{ { }}的正确理解与区别
v-text 与 v-html 指令都可以更新页面元素的内容,不同的是,v-text 会将数据以字符串文本的形式更新,而 v-html 则是将数据以 html 标签的形式更新。当变量的值含有 html 标记时(如: <ahref=“http://www.baidu.com”>百度),v-html 会解析 html标记,v-text 就会原样显示。
在更新数据上,我们也可以使用 Mustache 语法(即{ {}})进行更新数据,不同于 v-text、v-html 指令,{ {}}表达式只会更新原本占位插值所在的数据内容,而 v-text、v-html 指令则会替换掉整个的内容
<body>
<!-- dom部分 view部分 -->
<div id="app">
<p>+++++++++ {
{msg}} -----------</p>
<p v-text="msg">=================</p>
<p v-text="msgHtml">==============</p>
<p v-html="msgHtml">============</p>
</div>
<!-- js部分 -->
<script>
// model部分
var datamodel = {
msg: "helloworld",
msgHtml:"<a href='http://www.baidu.com'>百度</a>"
}
// viewmodel
new Vue({
el: "#app",//element
data:datamodel
})
</script>
</body>
运行结果:
上面三种形式对于数据间的交互都是单向的,即只能将vue 实例里的值传递给页面,页面对数据值的任何操作却无法传递给model
2.4、v-model
在表单控件或者组件上创建双向绑定。
<div id="app">
<!--显示数据-->
{
{msg}}
<!--使用v-model将input框里的数据和data中的数据进行双向绑定,
v-model:value="msg"可以省略value成v-model="msg"-->
<input type="text" v-model="msg">
</div>
<script>
var vm= new Vue({
el: '#app', data: {
msg: 'hello world', }
});
</script>
此时改变输入框的值,data中msg的值也会跟着发生改变
数据的双向绑定:
{
{msg}} :data.msg-->msg
<input type="text" v-model="msg"> :input.msg-->data.msg
再次认识 MVVM 框架
MVVM 中最重要的一个特性,可以说就是数据的双向绑定,而vue 作为一个 MVVM 框架,理所应当的实现了数据的双向绑定,所以我们可以使用内置的 v-model 指令完成数据在 View 与Model 间的双向绑定。
当然,因为只有表单元素可以与用户进行交互,所以我们只能使用 v-model 指令在表单控件上创建双向绑定。对于组件的双向绑定,我们后续讲解。
2.5、v-cloak
2.5.1、{ {}}模板语法的不足
上面{ {}}模板语法还有一个不足:可能会出现闪烁问题,就是可能页面数据还没加载渲染完成,就提前看到了两对{}。
实际应用中可能就是 vue 实例中 data 数据,比如可能是通过发送异步请求获取数据,数据来自于网络(服务器),由于网络或者数据量大,需要一定的时间,这个时候 vue 中的 data 尚没有数据,就不会去渲染 view,那么在 view 中就会提前看到类似{ {msg}},这就不太合适,所以需要在数据尚未渲染加载完成时不要让类似{ {msg}}出现。
2.5.2、使用 v-cloak 来解决
可以使用 v-cloak 来解决。使用 v-cloak,需要配合 css 样式一起使用,否则不会生效。通过 css 样式先设置为不显示,在数据渲染完成之后就会自动修改 display
<style>
[v-cloak] {
display: none;
}
</style>
</head>
<body>
<div id="app">
<h3 v-cloak> {
{msg}}</h3>
</div>
<script>
var vm = new Vue({
el: '#app', data: {
msg: '欢迎来到徐照兴课堂', },// 使用 created 函数作用就是测试页面尚未渲染数据时提前看到了{
{}},created 是 vue 生命周期中的一个钩子函数,刚创建vue实例后立马执行钩子函数,页面尚未渲染数据
created: function () {
alert('vue 实例刚创建,页面尚未渲染数据')
}
});
</script>
</body>
2.6、v-bind
v-bind 可以用来在标签上绑定标签的属性(例如:img 的 src、title 属性等等)和样式(可以用 style 的形式进行内联样式的绑定,也可以通过指定 class 的形式指定样式),同时,对于绑定的内容,是做为一个 js 变量,因此,我们可以对该内容进行编写合法的 js 表达式
语法: v-bind:属性="值"
属性就是普通 html 属性,值就来自于 vue 中的数据
v-bind 可以简写为:
如:v-bind:src=" "简写为:src=" "
<!-- 所有属性(指普通 html 属性)都一样,只要在前面加一个:
即表示访问到 vue 中的数据[属性],也就是所谓的绑定属性 -->
<img v-bind:src="url" :width="w" :height="h+'px'" :title="msg+'欢迎您'"
绑定的值也可以是表达式,如上述的h+'px'、msg+'欢迎您'
2.7、v-bind 绑定 class 和 style 属性
绑定 class 和 style 时语法相对比较复杂些。
1、绑定class:
:class=“fontmyvar” 双引号是到data里取数据
:class=“‘fontmy’” 要去style中取数据要再加一个单引号
:class=“[fontmyvar,bgmyvar]” 同时运用多个样式要用数组形式
:class=“{fontmy:flag,bgmy:false}” json 形式,键值对,键就是样式名,值固定为布尔型,即 true 或 false,true 表示应用该样式,false 表示不应用
this表示现在这个vue对象
<style>
.fontmy{
color:red;
font-size:20px;
}
.bgmy{
background-color: royalblue;
}
</style>
</head>
<body>
<div id="app">
<!-- 普通 css 绑定 -->
<p class="fontmy">徐照兴</p>
<!-- 直接这样绑定不行,加了:表示到 vue 中去找 fontmy 属性 -->
<!-- <p :class="fontmy">徐照兴</p> -->
<!-- 正确方式 1,直接在原来的类名外面写上一对单引号 -->
<p :class="'fontmy'">徐照兴 1</p>
<!-- 正确方式 2:通过变量形式 -->
<p :class="fontmyvar">徐照兴 2</p>
<!-- 正确方式 3:应用多个样式,用数组形式,数组值为多个属性变
量值 -->
<p :class="[fontmyvar,bgmyvar]">徐照兴 3</p>
<!-- 正确方式 4(常用):json 形式,键值对,键就是样式名,值
固定为布尔型,即 true 或 false,true 表示应用该样式,false 表示不应用 -->
<!-- 当然直接写 true 或 false 也就是写死,可以用变量,比如 flag,
就这表示来自 vue 中的值 -->
<p :class="{fontmy:flag,bgmy:false}">徐照兴 4</p>
<p :class="{fontmy:num>0,bgmy:false}">徐照兴 5</p>
<!--上面键值对如果太长了,影响阅读,正确方式 5:通过变量引
用 json 形式 -->
<p :class="varStyle">徐照兴 6</p>
</div>
<script>
var vm = new Vue({
el: "#app", data: {
fontmyvar:'fontmy',
bgmyvar:'bgmy',
flag:true,
num:-3,
varStyle:{
fontmy:true,
bgmy:true
// 这个地方也可使用 flag 指定,但要在前面加上 this,即 this.flag
}
}
})
</script>
</body>
运行效果:
2、绑定style:
style里面的属性名要遵循驼峰命名法,属性值需要单引号引起来。
驼峰命名法:第一个单词以小写字母开始;从第二个单词开始以后的每个单词的首字母都采用大写字母。
vue中class使用font-size:20px,但在style中不允许使用-,直接使用驼峰命名法且属性值要用单引号:fontSize:‘20px’
<div id="app">
<!-- 内嵌样式的绑定 -->
<p :style="myStyle">徐照兴 1</p>
<!-- 内嵌样式的绑定,使用数组形式 -->
<p :style="[myStyle,myStyle2]">徐照兴 2</p>
</div>
<script>
var vm = new Vue({
el: "#app", data: {
myStyle:{
// 注意这里的属性名要使用驼峰命名法,属性值需要单引号引起来
//驼峰命名法:第一个单词以小写字母开始;从第二个单词开始以后的每个单词的首字母都采用大写字母
color:'blue', fontSize:'30px' },
myStyle2:{
backgroundColor:'#ccc' }
}
})
</script>
运行结果:
2.8、v-on指令及this、methods、push的含义
用法:
v-on:事件名=”函数”。
事件名比如:click、dblclick、mousedown、mouseup 等等。
v-on:可以简写为@
<body>
<div id="app">
<button @click="show()">点我</button>
<button v-on:click="show()">点我</button>
<hr>
<button @mouseover="show">鼠标经过时执行</button>
<button @dblclick="show">鼠标双击时执行</button>
<hr>
<button @click="add">向数组中添加一个元素</button>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
arr:[12,23,34,45]
},
methods: {
show() {
// alert("1111")
console.log("这是一个show方法")
},
add(){
console.log(this)
console.log(this===vm)
this.arr.push(88)
vm.arr.push(99)
console.log(this.arr)
this.show();
}
},
})
</script>
</body>
结果:
上述项目使用了v-on和@来绑定了事件,此外绑定的事件必须要在vue实例中的methods里面定义,并且事件也可以有参数。 可以看出上述使用===号来判断this是否全等于vm这个vue实例,控制台输出为true,
2.9、v-if
v-if 指令是根据表达式的真假值判断元素的显示与否。
v-if和v-else可以组合成三种组合(语法和逻辑与平时的if-else是一样的):
单分支:v-if
双分支:v-if v-else
多分支v-if v-elseif v-else
<body>
<div id="app">
<div v-if="flag">Yes</div>
<div v-else>no</div>
<div v-if="grade>90">优秀</div>
<div v-else-if="grade>70">中等</div>
<div v-else-if="grade>60">及格</div>
<div v-else>不及格</div>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
flag:false,
grade:78
},
methods: {
},
})
</script>
</body>
结果:
特点:当 flag 值为 false 时 dom 元素会销毁,当为 true 时又会重新创建,如下 2 个图所示。
当需要同时隐藏多个div或其他标签时可以将多个div或其他标签放入template中通过改变template的v-if属性来同时显示或隐藏多个div或其他标签
2.10、v-show
2.10.1、v-show
v-show 指令也是根据表达式的真假值判断元素的显示与否,和v-if类似。
<body>
<div id="app">
<h1 v-show="flag">徐照兴欢迎您!</h1>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
flag: false,
},
methods: {
},
})
</script>
</body>
特点:带有 v-show 的元素始终会被渲染并保留在 DOM 中。 v-show 只是简单地切换元素的 CSS 属性 display。
flag 为 true 时效果:
flag 为 false 时效果:
2.10.2、v-show VS v-if
用来根据表达式的值显示或隐藏元素,v-show 是通过display 实现,显示与隐藏只是切换 display 属性;v-if 每次删除后重新创建,即显示与隐藏是在销毁与创建元素之间切换。
<div id="app">
<!-- v-show 后面也可以直接跟 true 或 false,也可以使用 vue
实例中的对象(因为 v 指令都可以访问 vue 实例中的数据 -->
<div style="width:100px;height:100px;background-color:r
ed;" v-show="flag">欢迎来到徐照兴课堂</div>
<!-- 通过下面按钮来切换上面 div 的显示与隐藏 -->
<hr>
<!-- 第一种方法 -->
<!-- <button v-on:click="change">隐藏</button> -->
<button v-on:click="change">隐藏/显示</button>
<!--第二种方法:事件里也可以直接写一个语句 -->
<button v-on:click="flag=false">隐藏</button>
<!-- 显示与隐藏之间切换 -->
<button v-on:click="flag=!flag">隐藏/显示
</button>
</div>
<script>
var vm = new Vue({
el: "#app", data: {
//存储数据地方
flag:true
},methods:{
change(){
// this.flag=false;//隐藏
this.flag=!this.flag;//隐藏与显示切换
}
}
})
</script>
结果:
使用this.flag=!this.flag;取反,可以反复单击该按钮改变flag的值并显示或隐藏上述div,为true时改为false,为false时改为true
分析:上面是通过 v-show 显示与隐藏,切换到代码查看器,会发现 div 的显示与隐藏是通过 display 是否为 none。
如果把 v-show 换成 v-if,则当 v-if 后面表达式值为 false 时,是销毁整个 div 元素,为 true 时,则重新创建。
1、v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不
做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多——不管初始条件是什么,元素
总是会被渲染,并且只是简单地基于 CSS 进行切换。
2、v-show 不支持 <template> 元素,也不支持 v-else。
一般来说,v-if 有更高的切换开销,而 v-show 有更高的
初始渲染开销。因此,当我们需要频繁控制元素的显示与否时,
推荐使用v-show 指令,避免因为使用 v-if 指令而造成的高性能消耗。
2.11、v-for
v-for 指令,可以对数组、对象、数字、字符串进行循环,获取到源数据的每一个值。使用 v-for 指令,必须使用特定语法 item in items ,其中 items 是源数据(数组、字符串等),而 item 则是当前遍历的元素的别名,这里类似于 C# 中的 foreach 的循环格式。
2.11.1、循环数组
<div id="app">
<ul>
<li v-for="value in arr">
{
{ value }}
</li>
</ul>
</div>
<script>
var app4 = new Vue({
el: '#app', data: {
arr: [1,2,3,4,5]
}
})
</script>
运行结果:
2.11.2、循环对象
<div id="app">
<ul>
<!-- 循环输出的是对象 users 的值 -->
<li v-for="value in user">{
{value}}</li>
</ul>
<ul>
<!-- 循环输出的是对象 user 的键、值及索引 -->
<li v-for="(value,key,index) in user">{
{index}}:{
{key}}={
{v
alue}}</li>
</ul>
<ul>
</div>
<script>
var app4 = new Vue({
el: '#app', data: {
arr: [1,2,3,4,5], user:{
id:1,username:'张三',age:20,sex:'男'}, }
})
</script>
运行结果:
2.11.3、循环对象数组(指数组元素值为对象)
<div id="app">
<ul>
<!-- 循环输出的是对象 users 的值 user.属性输出具体某属性值-->
<li v-for="(user,index) in users">
{
{index+1}}- {
{user.id}}-{
{user.username}}-{
{user.sex}}
</li>
</ul>
</div>
<script>
var vm = new Vue({
el: '#app', data: {
users:[
{
id:1,username:'张三',age:20,sex:'男'}, {
id:2,username:'李四',age:22,sex:'女'}, {
id:3,username:'王五',age:23,sex:'男'}, ]
}
})
</script>
运行结果:
2.11.4、遍历数字与字符串
<!-- 遍历数字 结果 12345-->
<span v-for="item in 5" :key="item">{
{ item }}</span>
<hr>
<!-- 遍历字符串结果 徐照兴 -->
<span v-for="item in '徐照兴'" :key="item">{
{ item }}</span
结果:
使用 v-for 时尽量提供 key,提高修改元素的效率
通过指定:key 属性为每个元素绑定一个唯一的 key(index唯一也可以),其优势是当更新元素时可重用元素提高效率。
也就是说假设数组 arr2 元素值发生变化时,如果没有:key
属性,那么会把 arr2 所有值先删除再重新插入。有 key 的话就会重用原有元素,也就是在原先基础上修改
<div id="app">
<ul>
<li v-for="value in arr2">{
{value}}</li>
<hr>
<!-- 通过指定:key 属性为每个元素绑定一个唯一的 key,其优
势是当更新元素时可重用元素提高效率 -->
<!-- 也就是说假设数组 arr2 元素值发生变化时,如果没有:key
属性,那么会把 arr2 所有值先删除再重新插入。有 key 的话就会重用
原有元素,也就是在原先基础上修改 -->
<li v-for="(value,key) in arr2" :key="key">{
{value}}</li>
</ul>
</div>
<script>
var app4 = new Vue({
el: '#app', data: {
arr2: [1,2,3,4,5], }
})
</script>
2.12、v-once 与 v-pre
v-once 只绑定一次。
v-pre 不解析{ {}}
<body>
<div id="app">
<input type="text" v-model="msg">{
{msg}}</input>
<!-- 只绑定一次 ,后面修改了 msg 的值这里不变-->
<h3 v-once>{
{msg}}</h3>
<!-- 这里我就想把{
{}}显示出来怎么办? 加一个 v-pre 指令-->
<h3 v-pre>{
{msg}}</h3>
<!-- <h3 v-pre>{
{hello vue}}</h3> 这里如果没有 v-pre 指令就会报错,
因为会认为 hello vue 是 data 里的一个属性,而实际不存在,所以会报错-->
<h3 v-pre>{
{hello vue}}</h3>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
msg:"欢迎来到小豆子学堂"
},
})
</script>
</body>
结果:
此外,v-pre指令会导致跳过这个元素和它的子元素的编译过程。加快编译。
例如:网页中的一篇文章,文章内容不需要被 Vue 管理渲染,则可以在此元素上添加 v-pre 指令,将会忽略对文章编译(也就是不去检测文章内容是否含有 vue 的语法,并对其进行解析),从而提高性能。
2.12、v-model 常用的三个修饰符
2.12.1、.lazy 修饰符
在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步。也就是文本框中输入的与显示的同步,每输入一个字符都会同步显示。而可以添加.lazy 修饰符,从而转变为失去焦点同步。也就是说现在在文本框中输入字符是,msg 的值不会及时改变,要等光标移到文本框外面才同步改变。
<body>
<div id="app">
<input type="text" v-model.lazy="msg">{
{msg}}</input>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
msg:"hello"
},
})
</script>
</body>
结果:
2.12.2、.number 修饰符
如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 number 修饰符
<body>
<div id="app">
<input type="text" v-model.lazy="msg">{
{msg}}</input>
<input type="text" v-model.lazy="num1">{
{num1}}</input>
<input type="text" v-model.lazy="num2">{
{num2}}</input>
<br>
<!-- 要求 num1 和 num2 的和,写{
{num1+num2}} 的话num1+num2 会变成字符串的连接 -->
<!--{
{parseFloat(num1)+parseFloat(num2)}} -->
{
{num1+num2}}
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
msg:"hello",
num1:1,
num2:2
},
})
</script>
</body>
v-model 后面加了.number,即是转为数值型数据,就只能是求和。
也可以用不加.number使用 parseInt 进行转换,即上面的注释{
{parseFloat(num1)+parseFloat(num2)}},效果一样是求和。
2.12.3、 .trim 修饰符
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符
<body>
<div id="app">
<input type="text" v-model.trim="msg">{
{msg}}</input>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
msg:"hello",
},
})
</script>
</body>
结果:
有了 trim 修饰,只要光标离开了文本框在其他地方单击 下,两端若有空格就会自动去掉
三、v-if 与 v-for 结合使用(循环与条件的结合)
当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级,
当你只想为部分项渲染节点时,这种优先级的机制会十分有用。也就是说当 v-if 与 v-for 一起使用时,v-for 循环在外,v-if 条件判断在内部。
<body>
<div id="app">
<ul>
<li v-for="item in items" v-if="item.isOK">{
{item.text}}</li>
</ul>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
arr:[1,2,3,4,5],
items:[
{
text:'vue',isOK:true},
{
text:'react',isOK:true},
{
text:'angular',isOK:true},
{
text:'html5',isOK:false},
{
text:'css3',isOK:false}
]
},
})
</script>
</body>
结果:
而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素上。
<body>
<div id="app">
<ul v-if="isOK">
<li v-for="item in items">{
{item.text}}</li>
</ul>
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
isOK:true,
items:[
{
text:'vue',isOK:true},
{
text:'react',isOK:true},
{
text:'angular',isOK:true},
{
text:'html5',isOK:false},
{
text:'css3',isOK:false}
]
},
})
</script>
</body>
运行结果:
如果我把上面 isOK 后面的 true 改为 false,就不会显示整个无序列表内容。