1. 内置指令
1.1. v-cloat
这个指令保留在元素上直到关联的实例结束编译
主要作用:处理闪烁问题
使用:
css
<div v-cloak>
{{ message }}
</div>
css
[v-cloak] {
display: none;
}
效果:
不会直接显示在页面中,直到 js 文件编译结束,这个属性将会被销毁,从而在 html 中无法找到属性v-cloak,所以display: none;
无法执行,就会将元素展示出来。
1.2. v-text
将数据以动态的方式绑定在元素上,从而显示在页面中。
注意:如果是需要更新部分的内容,那么需要使用到插值表达式 {{}}
使用:
ini
<span v-text="msg"></span>
css
<span>{{msg}}</span>
区分:
<span v-text="msg"></span>
:不会出现闪烁问题
<span>{{msg}}</span>
:会出现闪烁问题,需要结合 v-cloak
指令处理闪烁问题
特点:
- 不会解析数据中的标签,也就是说,如果数据中包含标签,
v-text
指令会直接将数据原样输出到页面中,不会进行 html 解析
1.3. v-html
更新元素的 innerHTml
使用:
css
<div v-html="html"></div>
区分:
<div v-html="html"></div>
:不会出现闪烁问题
特点:
- 会解析数据中的标签
1.4. v-show
根据表达式的真假值,切换元素的 display 的 css 属性值,当条件变化时该指令触发过度效果
ini
<div id='app'>
<p v-show='boolean'>显示隐藏文本</p>
</div>
php
nwe Vue({
el:'#app',
data:{
boolean:false
}
})
上面这个例子中的 p 标签,只有修改 boolean 的值为 true 时才会显示文本,本质就是 display:none
和 display:block
的切换
1.5. v-if 系列
1.5.1. v-if
根据表达式的值的 truthiness 来有条件地渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。
ini
<div v-if="Math.random() > 0.5">
Now you see me
</div>
1.5.2. v-else
前一兄弟元素必须有 v-if
或 v-else-if
xml
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
1.5.3. v-else-if
前一兄弟元素必须有 v-if
或 v-else-if
css
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
1.6. v-show 和 v-if 系列的区别
这两个指令都是用于条件性的显示元素的指令,但是它们本质上还是有一些区别的:
渲染机制不同:
- v-if 是真正的"条件渲染",他会确保条件块内的时间监听器和子组件再切换时被销毁和重建。当条件为 false 时,元素及其所有子元素会被完全移除出 DOM,也就是说在 html 结构中并没有这样一个元素存在。
- v-show 则是简单的切换元素的 css 的
diaplay
属性,不管初始条件如何,元素总是会被渲染出来保留在 DOM 中,只是显示或者不显示
初始渲染开销不同:
v-if
是惰性的,如果初始条件是 false,则什么也不做,只有当条件首次为 true 的时候,才会渲染条件块v-show
则不管初始条件是什么,元素总是会被渲染,所以有跟高的初始渲染开销
切换开销不同:
v-if
在切换时有较高的开销,因为它会完全销毁和重建条件快内的 DOM 元素和组件实例v-show
的切换开销较小,只是切换css
的display
属性,DOM 元素始终保留
功能支持不同
v-if
支持v-else
和v-else-if
分支,可以在template
元素上使用v-show
不支持v-else
,也不能在template
元素上使用
以上说的就是 vue 中的条件渲染。
1.7. v-for
基于源数据多次渲染元素或模板块。此指令之值,必须使用特定语法 alias in expression
,为当前遍历的元素提供别名:
ini
<div v-for="item in items">
{{ item.text }}
</div>
关于 v-for 我们就来看一看 vue 中的列表渲染,注意这也是一个重点:
我们可以用 v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用 item in items
形式的特殊语法,其中 items
是源数据数组,而 item
则是被迭代的数组元素的别名。
ini
<ul id="example-1">
<li v-for="item in items" :key="item.message">
{{ item.message }}
</li>
</ul>
css
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})

可以看到,我们在 DOM 结构中只有一个 li 但是实际渲染却有两个,也就是说我们通过 v-for 将 items 的数据列表,渲染到了 DOM 中
在 v-for
块中,我们可以访问所有父作用域的 property。v-for
还支持一个可选的第二个参数,即当前项的索引。
ini
<ul id="example-1">
<li v-for="item,index in items" :key="item.message">
{{ item.message }}
</li>
</ul>
除了在 v-for 中渲染数组列表外,还可以在 v-for 中使用对象
1.7.1. v-for 中使用对象
ini
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
css
new Vue({
el: '#v-for-object',
data: {
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
})


css
<div v-for="(value, name) in object">
{{ name }}: {{ value }}
</div>

第一个参数为对象中的键值,第二个参数为对象中的键名
同样也可以获取到索引值,也就是加上第三个参数
css
<div v-for="(value, name, index) in object">
{{ index }}. {{ name }}: {{ value }}
</div>

1.7.2. 维护状态
当 Vue 正在更新使用 v-for
渲染的元素列表时,它默认使用"就地更新"的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

就像这张图一样,vue 不会去操作 DOM 元素去移动 2 和 3 的位置,而是在原有位置,直接更新其中的数据
这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key
属性
xml
<div v-for="item in items" v-bind:key="item.id">
<!-- 内容 -->
</div>
1.7.3. 显示过滤/排序后的结果
这在实际的开发中还是很有用的,比如:有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。
ini
<li v-for="n in evenNumbers">{{ n }}</li>
javascript
data: {
numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
evenNumbers: function () {
return this.numbers.filter(function (number) {
return number % 2 === 0
})
}
}
那么现在就来解释一下上述的代码:
- 首先我们先定义了计算属性
evenNumbers
- 然后通过计算属性返回过滤后的新数组
需要注意的是,如果你需要修改数据的话,需要去直接操作原始数据,不可以操作计算属性的数据,因为计算属性通常提供 getter 方法,但是如果你不怕麻烦也可以手动设置计算属性的 setter 方法,手动的去做响应式数据,但是我觉得还是直接去改动原数据就可以了。
比如数据的结构是这样的:
[[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
如果数据结构上以上这样可能就不是很适用
ini
<ul v-for="set in sets">
<li v-for="n in even(set)">{{ n }}</li>
</ul>
lua
data: {
sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
},
methods: {
even: function (numbers) {
return numbers.filter(function (number) {
return number % 2 === 0
})
}
}
我们继续来说一下这种情况,这种情况,一个计算属性可能无法达到我们预期的效果,那么我们就不应该还去使用计算属性了,我们可以去定义一个方法来处理其中的逻辑。
1.8. v-on
绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略
在这里我们提到了修饰符,这里的修饰符叫做事件修饰符
1.8.1. 事件修饰符
.stop
- 调用event.stopPropagation()
.prevent
- 调用event.preventDefault()
.capture
- 添加事件侦听器时使用 capture 模式.self
- 只当事件是从侦听器绑定的元素本身触发时才触发回调.once
- 只触发一次回调.passive
- (2.3.0) 以{ passive: true }
模式添加侦听器
阻止单击事件继续传播,也就是阻止冒泡
arduino
<a v-on:click.stop="doThis"></a>
阻止默认行为
ini
<button @click.prevent="doThis"></button>
阻止默认行为,没有表达式
css
<form @submit.prevent></form>
添加事件监听器时使用事件捕获模式
ini
<div v-on:click.capture="doThis">...</div>
让事件在捕获阶段就触发
只当在 event.target 是当前元素自身时触发处理函数
ini
<div v-on:click.self="doThat">...</div>
只触发一次回调
ini
<a v-on:click.once="doThis"></a>
滚动事件的默认行为 (即滚动行为) 将会立即触发
ini
<div v-on:scroll.passive="onScroll">...</div>
接下来我们再来看看如何去绑定一个事件,相比在刚刚看上述内容的时候有一点懵,那么在这里来说语法格式:
xml
<a v-on:事件类型='事件名称'></a>
简写形式:
xml
<a @事件类型='事件名称'></a>
1.9. v-bind
动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。使其具有响应式数据的特征。
ini
<img v-bind:src="imageSrc">
这里需要特别说两个属性的绑定:
- class的绑定
- style的绑定
1.9.1. class 的绑定
ini
<div v-bind:class="{ active: isActive }"></div>
isActive
的值应该是一个 Boolean 类型的值,去动态的控制是否添加这一类名
动态绑定的 class 可以和静态的 class 共存
arduino
<div class='box' v-bind:class="{ active: isActive }"></div>
当然也可以使用计算属性去返回一个对象来动态控制:
ini
<div v-bind:class="classObject"></div>
kotlin
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
ini
<div v-bind:class="[activeClass, errorClass]"></div>
css
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
同样的可以在数组中嵌套对象来控制是否使用当前 class 名
ini
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
style 的绑定语法是相似的,这里就不作更多的说明,如需要,可以在评论去说明,会尽快更新。
最后说一下简写的绑定语法
ruby
<div :class="[{ active: isActive }, errorClass]"></div>
可以将 v-bind 替换为:
1.10. v-model
在表单控件或者组件上创建双向绑定
在这里简单的说明一下双向绑定,双向绑定就是当数据发生变化的时候,页面会随之实时的变化,当页面发生变化的时候,数据也会实时的发生改变。大家可以先这样理解,之后我会单一出一篇文章仔细说明 Vue 双向绑定原理
xml
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
那么常用的指令我们就说到这里,不过已经将大部分的指令都提及到了,如果有其他的需要,可以发表在评论区。接下来我们就说点有意思的,大家可能已经知道定我要说什么了,对,就是自定义指令,这就让我们可以更灵活的使用指令了。
2. 自定义指令
有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令,接下来通过一个聚焦输入框例子来说明如何去自定义一个指令:
事实上,只要你在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。现在让我们用指令来实现这个功能
javascript
Vue.directive('focus', {//focus就是指令的名称
// 当被绑定的元素插入到 DOM 中时......
inserted: function (el) {//el就是指令所绑定的标签
// 聚焦元素
el.focus()
}
})
css
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
3. 结语
如果大家对文章有任何疑问,都可以在评论区来聊一聊,需要补充也可以提及,今天的分享就到这里