Skip to main content

指令系统

指令是带有 v- 前缀的特殊 attribute,Vue 提供了许多内置指令。

v-bind

v-bind 可以响应式地绑定一个 attribute,如果绑定的值是 null 或者 undefined,那么该 attribute 将会从渲染的元素上移除。

<div v-bind:id="dynamicId"></div>

简写语法

<div :id="dynamicId"></div>

动态绑定多个值

<div v-bind="objectOfAttrs"></div>
const objectOfAttrs = {
id: 'container',
class: 'wrapper'
}

v-html

v-html 可以动态渲染任意 HTML。

<span v-html="rawHtml"></span>

span 的内容将会被替换为 rawHtml 属性的值,插值为纯 HTML——数据绑定将会被忽略。

v-if

用于条件性地渲染一块内容。

<p v-if="seen">Now you see me</p>

v-if 指令会基于表达式 seen 的值的真假来移除/插入该 <p> 元素。

可以使用以下两个指令,但必须跟在一个 v-if 或者 v-else-if 元素后面。

  • v-else-if
  • v-else

v-show

用来按条件显示一个元素。

v-show 会在 DOM 渲染中保留该元素,v-show 仅切换了 display 的 CSS 属性。

v-show 不支持在 <template> 元素上使用,也不能和 v-else 搭配使用。

<h1 v-show="seen">Now you see me</h1>

v-if与v-show的区别

v-if 是真实的按条件渲染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建。

v-show 则简单许多,元素无论初始条件如何,始终会被渲染,只有 CSS display 属性会被切换。

总的来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要频繁切换,则使用 v-show 较好;如果在运行时绑定条件很少改变,则 v-if 会更合适。

v-for

v-for 可以基于一个数组来渲染一个列表。

const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
<li v-for="(item, index) in items">
{{ item.message }} - {{ index }}
</li>

v-for 也可以遍历一个对象的所有属性,遍历的顺序会基于对该对象调用 Object.keys() 的返回值来决定。

const myObject = reactive({
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
})
<li v-for="(value, key, index) in myObject">
{{ index }}. {{ key }}: {{ value }}
</li>

v-for 还可以直接接受一个整数值,但 n 的初值是从 1 开始而非 0。

<span v-for="n in 10">{{ n }}</span>

v-for 的其他知识点

  • 当 v-if 和 v-for 同时存在于一个节点上时,v-if 的优先级更高。
<!--
这会抛出一个错误,因为属性 todo 此时
没有在该实例上定义
-->
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo.name }}
</li>
  • 为了跟踪每个节点的标识,从而重用和重新排序现有的元素,需要为每个元素对应的块提供一个唯一的 key attribute
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
  • 可以直接在组件上使用 v-for,但不会自动将任何数据传递给组件。
<MyComponent
v-for="(item, index) in items"
:key="item.id"
:item="item"
:index="index"
/>

v-on

v-on 可以监听 DOM 事件。

<a v-on:click="doSomething"> ... </a>

简写语法

<a @click="doSomething"> ... </a>

如果是简单场景,可以直接使用内联事件

<button @click="count++">Add 1</button>

访问事件参数

<!-- 使用特殊的 $event 变量 -->
<button @click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>

<!-- 使用内联箭头函数 -->
<button @click="(event) => warn('Form cannot be submitted yet.', event)">
Submit
</button>
function warn(message, event) {
// 这里可以访问原生事件
if (event) {
event.preventDefault()
}
alert(message)
}

v-model

v-model 可以简化手动连接值绑定和更改事件监听器。

v-model 会根据所使用的元素自动使用对应的 DOM 属性和事件组合,但会忽略任何表单元素上初始的 value、checked 或 selected attribute。

<!-- 手动连接值绑定和更改事件监听器 -->
<input
:value="text"
@input="event => text = event.target.value">

<!-- 使用 v-model 简化 -->
<input v-model="text">

修饰符

修饰符描述
.lazy默认情况下,v-model 会在每次 input 事件后更新数据,加 lazy 修饰符改为在每次 change 事件后更新数据
.number用户输入自动转换为数字,如果该值无法被 parseFloat() 处理,那么将返回原始值
.trim自动去除用户输入内容中两端的空格

事件修饰符

事件修饰符是以点开头的特殊后缀,表明指令需要以一些特殊的方式被绑定。

<form @submit.stop.prevent="onSubmit">...</form>
事件修饰符描述
.stop对触发的事件停止冒泡传递
.prevent对触发的事件调用 event.preventDefault(),阻止事件的默认行为
.self仅当 event.target 是元素本身时才会触发事件
.capture添加事件监听器时,使用 capture 捕获模式,从根元素向触发元素传播,与冒泡相反
.once事件最多被触发一次,之后的触发不会再有效
.passive事件的默认行为将立即发生,一般用于触摸事件的监听器,可以用来改善移动端设备的滚屏性能

按键修饰符

在监听键盘事件时,我们经常需要检查特定的按键。

<!-- 仅在 key 为 Enter 时调用 submit -->
<input @keyup.enter="submit" />
按键修饰符描述
.enter
.tab
.delete捕获 Delete 和 Backspace 两个按键
.esc
.space
.up
.down
.left
.right
.ctrl
.alt
.shift
.meta在 Mac 键盘上,meta 是 Command 键 (⌘)。在 Windows 键盘上,meta 键是 Windows 键 (⊞)
.exact允许控制只有在按下指定的键,而没有按下其他键时才会触发事件
<!-- 当按下 Ctrl 时,即使同时按下 Alt 或 Shift 也会触发 -->
<button @click.ctrl="onClick">A</button>

<!-- 仅当按下 Ctrl 且未按任何其他键时才会触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>

<!-- 仅当没有按下任何系统按键时触发 -->
<button @click.exact="onClick">A</button>

鼠标按键修饰符

用于处理由特定鼠标按键触发的事件。

鼠标按键修饰符
.left
.right
.middle