指令简介

指令(Directives)是 Vue 模板中最具特色的语法,它们是带有 v- 前缀的特殊属性。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。

指令的基本结构

<element v-directive="expression"></element>

一个完整的指令包含:

  • 指令名称v- 前缀 + 指令名
  • 参数:指令名后的冒号和参数值
  • 修饰符:以点开头的特殊后缀
  • 表达式:引号内的 JavaScript 表达式
<a v-bind:href="url" target="_blank">链接</a>
<!--   ↑    ↑      ↑
      指令  参数   表达式
-->

<button v-on:click.prevent="handleSubmit">提交</button>
<!--        ↑    ↑   ↑       ↑
          指令 参数 修饰符  表达式
-->

常用指令概览

指令用途示例
v-text更新元素的 textContent<span v-text="msg"></span>
v-html更新元素的 innerHTML<div v-html="html"></div>
v-show切换 display 属性<div v-show="visible"></div>
v-if条件渲染<div v-if="seen"></div>
v-else否则分支<div v-else></div>
v-else-if否则如果<div v-else-if="type"></div>
v-for列表渲染<li v-for="item in list"></li>
v-on事件绑定<button v-on:click="fn"></button>
v-bind属性绑定<img v-bind:src="url">
v-model双向绑定<input v-model="value">
v-slot插槽<template v-slot:header></template>
v-pre跳过编译<span v-pre>{{ msg }}</span>
v-cloak防止闪烁<div v-cloak>{{ msg }}</div>
v-once只渲染一次<span v-once>{{ msg }}</span>

参数(Arguments)

一些指令可以接受参数,在指令名称后以冒号表示:

<!-- v-bind 参数:要绑定的属性名 -->
<img v-bind:src="imageSrc">
<a v-bind:href="url">链接</a>
<div v-bind:class="{ active: isActive }"></div>

<!-- v-on 参数:要监听的事件名 -->
<button v-on:click="doSomething">点击</button>
<input v-on:focus="onFocus">

动态参数

Vue 2.6.0+ 支持动态参数,用方括号括起来:

<!-- 动态属性名 -->
<a v-bind:[attributeName]="url">链接</a>

<!-- 动态事件名 -->
<button v-on:[eventName]="handler">按钮</button>
new Vue({
  data: {
    attributeName: 'href',
    eventName: 'click',
    url: 'https://vuejs.org'
  },
  methods: {
    handler: function() {
      console.log('clicked')
    }
  }
})

动态参数的限制

  1. 参数值必须是字符串,如果是 null 则移除绑定
  2. 参数表达式不能包含空格和引号
  3. 避免使用大写字符,因为 HTML 会将属性名转为小写
<!-- ❌ 错误:包含空格 -->
<a v-bind:['attr' + name]="value"></a>

<!-- ✅ 正确:使用计算属性 -->
<a v-bind:[computedAttr]="value"></a>

修饰符(Modifiers)

修饰符是以点开头的特殊后缀,用于指出指令应该以特殊方式绑定:

<!-- 阻止默认行为 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 阻止事件冒泡 -->
<div v-on:click.stop="doThis"></div>

<!-- 事件只触发一次 -->
<button v-on:click.once="doThis"></button>

<!-- 按键修饰符 -->
<input v-on:keyup.enter="submit">
<input v-on:keyup.esc="cancel">

<!-- 表单修饰符 -->
<input v-model.lazy="msg">
<input v-model.number="age">
<input v-model.trim="text">

常用修饰符

事件修饰符

修饰符说明
.stop阻止事件冒泡
.prevent阻止默认行为
.capture使用事件捕获模式
.self只当事件在该元素本身触发时触发
.once事件只触发一次
.passive提升移动端滚动性能

按键修饰符

修饰符键码
.enter回车
.tabTab
.escEsc
.space空格
.up / .down / .left / .right方向键

表单修饰符

修饰符说明
.lazy在 change 事件后同步
.number自动转为数字
.trim自动过滤首尾空格

缩写

Vue 为常用指令提供了缩写:

v-bind 缩写

<!-- 完整写法 -->
<a v-bind:href="url">链接</a>

<!-- 缩写 -->
<a :href="url">链接</a>

<!-- 动态参数缩写 -->
<a :[key]="value">链接</a>

v-on 缩写

<!-- 完整写法 -->
<button v-on:click="doSomething">点击</button>

<!-- 缩写 -->
<button @click="doSomething">点击</button>

<!-- 动态参数缩写 -->
<button @[event]="handler">点击</button>

v-text vs 插值表达式

v-text{{ }} 功能类似,但有细微差别:

<!-- 两种写法效果相同 -->
<span v-text="message"></span>
<span>{{ message }}</span>

<!-- 区别:v-text 会替换整个元素内容 -->
<p v-text="message">这段文字会被替换</p>

<!-- 插值表达式可以部分替换 -->
<p>前缀文字 {{ message }} 后缀文字</p>

v-once 指令

v-once 让元素和组件只渲染一次,后续重新渲染时视为静态内容:

<div id="app">
  <p v-once>{{ message }}</p>
  <p>{{ message }}</p>
  <button @click="message = 'Changed'">改变</button>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    message: 'Initial'
  }
})
</script>

点击按钮后,第一个 <p> 仍然显示 "Initial",第二个显示 "Changed"。

v-pre 指令

v-pre 跳过这个元素和它的子元素的编译过程:

<!-- 显示原始的 {{ message }},不会被编译 -->
<span v-pre>{{ message }}</span>

适合显示原始 Mustache 标签的场景。

v-cloak 指令

v-cloak 用于防止页面加载时出现未编译的 Mustache 标签:

<style>
[v-cloak] {
  display: none;
}
</style>

<div id="app" v-cloak>
  {{ message }}
</div>

在 Vue 实例编译完成前,带有 v-cloak 的元素会被隐藏,编译完成后自动移除该属性。

小结

指令是 Vue 模板的核心特性:

  • v- 前缀标识
  • 可以带参数和修饰符
  • 支持动态参数(2.6.0+)
  • v-bindv-on 有缩写形式

熟练掌握指令是编写 Vue 模板的基础。