指令系统
指令是带有 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 |