技术知识文章集合TECHNICAL ARCHIVE · 457 DOCUMENTS

显示模式

登录
ARCHIVE DOCUMENTVUE

Vue 常用修饰符大全

所属馆藏
Vue
文件格式
Markdown
原始路径
Vue/44-Vue常用修饰符大全
本文目录14 个章节
  1. 一、修饰符分为哪些类型
  2. 二、表单 v-model 修饰符
  3. 三、DOM 事件修饰符
  4. 四、鼠标按键修饰符
  5. 五、键盘修饰符
  6. 六、系统修饰键与事件顺序示例
  7. 七、v-bind 修饰符
  8. 八、.sync:Vue 2 与 Vue 3 的迁移
  9. 九、组件 v-model 的修饰符与版本差异
  10. 十、常见修饰符对照表
  11. 十一、实际使用建议
  12. 十二、总结
  13. 官方参考
  14. 原文出处

Vue 常用修饰符大全

Vue 修饰符是写在指令之后、以点号连接的特殊后缀。它们可以改变事件监听、表单同步或属性绑定的细节。

原文的 .lazy.trim.number、事件修饰符和 .sync 介绍大部分有基础价值,但存在两个明显错误:把 .sync 多处写成了 async,把 .passive 错误地解释成滚动事件的 .lazy。本文同时补充 Vue 2.7 与 Vue 3.5 的迁移边界。

一、修饰符分为哪些类型

常见修饰符可以按用途分为:

  1. 表单 v-model 修饰符.lazy.trim.number
  2. DOM 事件修饰符.stop.prevent.self.capture.once.passive
  3. 系统按键修饰符.ctrl.alt.shift.meta.exact
  4. 键盘按键修饰符.enter.tab.delete.esc.space.up.down.left.right 以及 kebab-case 按键名;
  5. 鼠标按键修饰符.left.right.middle
  6. v-bind 修饰符.prop.camel、Vue 3 的 .attr
  7. Vue 2 组件兼容写法.native.sync,它们在 Vue 3 中有迁移替代方案。

修饰符不是都在做同一种事情:.stop.prevent 是事件处理逻辑,.once.capture.passive 会影响监听器选项,.enter.ctrl 则是事件过滤条件。

二、表单 v-model 修饰符

1. .lazy

默认情况下,文本输入框的 v-model 在每次 input 事件后同步数据。.lazy 会改为在 change 事件后同步:

<template>
  <input v-model.lazy="description" />
  <p>{{ description }}</p>
</template>

.lazy 只改变同步时机,不是异步加载,也不是事件监听器的 passive 选项。

2. .trim

.trim 会去掉输入字符串两端的空白:

<input v-model.trim="name" />

它适合用户名、搜索关键字等文本输入。是否应该自动去除空格仍然取决于业务;密码、代码或需要保留空格的文本不应盲目使用。

3. .number

.number 尝试将输入转换成数字:

<input v-model.number="age" type="number" />

如果转换失败,Vue 会保留原始字符串;空输入也可能得到空字符串。不要只根据 HTML 的 type="number" 就假设后端一定会收到 number,提交前仍应进行类型校验。

Vue 3 对 type="number" 的原生输入会自动应用 number 行为,但显式写出 .number 更容易表达意图。

三、DOM 事件修饰符

1. .stop

调用 event.stopPropagation(),阻止事件继续向父元素传播:

<div @click="say('parent')">
  <button @click.stop="say('button')">点击</button>
</div>

点击按钮时,按钮处理器执行,但事件不会继续冒泡到父级 div.stop 不会阻止默认行为。

2. .prevent

调用 event.preventDefault(),阻止浏览器默认行为:

<form @submit.prevent="submitForm">
  <button type="submit">提交</button>
</form>

.prevent 不会阻止冒泡;如果同时需要阻止冒泡,应另加 .stop

3. .self

只有当事件的 target 就是当前元素自身时才执行:

<div @click.self="closePanel">
  <button>点击按钮不会触发 closePanel</button>
</div>

.self 不是“阻止事件冒泡”的另一种写法,而是过滤事件目标。子元素事件即使冒泡到当前元素,也不会通过 self 判断。

修饰符顺序会影响生成代码的顺序:

<!-- 先 prevent,再 self:子元素点击也可能被阻止默认行为 -->
<div @click.prevent.self="handle"></div>

<!-- 先判断 self,再 prevent:只处理元素自身点击的默认行为 -->
<div @click.self.prevent="handle"></div>

4. .once

监听器只执行一次:

<button @click.once="submitOnce">只提交一次</button>

.once 也可以用于组件事件,但它只控制监听器次数,不会让组件实例只创建一次。

5. .capture

使用事件捕获阶段监听。捕获阶段从外层向目标元素传播,目标和冒泡阶段则相反:

<div @click.capture="log('outer-capture')">
  <div @click.capture="log('middle-capture')">
    <button @click="log('button')">点击</button>
  </div>
</div>

典型顺序是外层捕获、内层捕获、目标处理,然后进入冒泡阶段。实际顺序还会受到 stopPropagation 和其他监听器的影响。

6. .passive

.passive 会以 passive: true 的选项注册事件监听器,告诉浏览器该监听器不会调用 preventDefault()

<div class="scroll-area" @scroll.passive="onScroll">
  <!-- ... -->
</div>

它的作用不是 .lazy,也不是让 onscroll “延迟触发”。在触摸、滚动等浏览器默认行为场景中,浏览器可以更早执行滚动,而不必等待监听器确认是否阻止默认行为。

不要同时使用 .passive.prevent passive 监听器已经声明不会阻止默认行为,浏览器会忽略或警告 preventDefault()

7. .native:仅 Vue 2 组件兼容写法

Vue 2 中,组件上的普通 @click 默认监听组件自定义事件;.native 可以把监听器绑定到组件根元素:

<!-- Vue 2.7 -->
<base-input @focus.native="handleFocus" />

它依赖组件有合适的单一根元素。如果组件根节点改变成 label 或多层结构,监听行为可能与预期不符。

Vue 3 已移除 .native。Vue 3 中应直接使用组件事件和 $emit/emit

<!-- Child.vue,Vue 3 -->
<script setup lang="ts">
const emit = defineEmits<{
  focus: []
}>()
</script>

<template>
  <input @focus="emit('focus')" />
</template>
<!-- Parent.vue -->
<Child @focus="handleFocus" />

如果 Vue 3 子组件没有声明某个事件,单根组件上的监听器可能按照 fallthrough 规则进入根元素;如果在 emits 中声明了该事件,它表示监听子组件显式触发的组件事件。多根组件需要显式处理 $attrs

参考:Vue 3 .native 移除Fallthrough Attributes

四、鼠标按键修饰符

Vue 提供:

  • .left:主指针按钮,通常是鼠标左键;
  • .right:次指针按钮,通常是鼠标右键;
  • .middle:辅助指针按钮,通常是鼠标中键。
<button @click.left="handleLeft">主按钮</button>
<button @click.right="handleRight">次按钮</button>
<button @click.middle="handleMiddle">辅助按钮</button>

不同浏览器和事件类型的 button 映射可能不同。Vue 2 编译器会对 click.rightclick.middle 做事件类型转换;Vue 3 运行时主要通过 MouseEvent.button 判断。对于复杂指针交互,可以直接读取事件对象。

五、键盘修饰符

1. 按键别名

<input @keyup.enter="submit" />
<input @keyup.esc="closeDialog" />
<input @keyup.page-down="handlePageDown" />

常见别名包括:

  • .enter
  • .tab
  • .delete(同时覆盖 Delete 和 Backspace)
  • .esc
  • .space
  • .up.down.left.right

Vue 3 支持使用 KeyboardEvent.key 对应的 kebab-case 名称,例如 page-down

2. 系统修饰键

<!-- Ctrl/Command + Enter 才触发 -->
<textarea @keydown.ctrl.enter="submit" />

<!-- 必须只有 Ctrl/Command,没有其他系统键 -->
<input @keyup.ctrl.exact="handleCtrlOnly" />

系统修饰键包括:

  • .ctrl
  • .alt
  • .shift
  • .meta(macOS Command、Windows 键等)
  • .exact

.exact 要求事件只包含指定的系统修饰键,不会阻止普通字符键本身。

3. keyCode 的版本边界

原文中的:

<!-- 不要把 keyCode 当作 Vue 3 当前写法 -->
<input @keyup.keyCode="shout" />

这不是正确的通用语法。Vue 2 时代可以使用数字 keyCode,例如:

<!-- Vue 2 历史写法:13 表示 Enter -->
<input @keyup.13="submit" />

也可以在 Vue 2 中配置 Vue.config.keyCodes 自定义别名。Vue 3 已移除数字 keyCode modifier 和 config.keyCodes,推荐使用按键别名或直接读取 event.key

<input @keyup="handleKeyup" />
function handleKeyup(event: KeyboardEvent) {
  if (event.key === 'Enter') {
    submit()
  }
}

参考:Vue 3 keyCode 迁移指南

六、系统修饰键与事件顺序示例

修饰符可以组合使用:

<!-- Ctrl/Command + 点击,并且阻止默认行为 -->
<a href="/settings" @click.ctrl.prevent="openSettings">
  设置
</a>

要注意操作系统和浏览器差异:

  • macOS 常用 .meta 表示 Command;
  • Windows/Linux 常用 .ctrl 表示 Ctrl;
  • 触摸设备不一定产生传统鼠标按键事件;
  • 复杂键盘布局不要只依赖 keyCode,优先使用 event.keyevent.code

七、v-bind 修饰符

1. .prop

.prop 强制把值设置为 DOM property,而不是 HTML attribute:

<input :value.prop="value" />

它不是用来“隐藏数据”或“避免污染 HTML”的。property 和 attribute 是浏览器中不同的概念:

  • attribute 是 HTML 标签上的特性;
  • property 是 DOM 对象上的 JavaScript 属性;
  • Vue 3 通常会根据元素和属性自动选择合适的绑定方式;
  • 只有在需要明确控制时才使用 .prop.attr

2. .camel

.camel 将连字符属性转成 camelCase,主要用于 in-DOM 模板或 SVG 属性名:

<!-- 需要把 view-box 绑定成 viewBox -->
<svg :view-box.camel="viewBox"></svg>

在 SFC 预编译模板中,编译器通常可以直接保留正确的大小写,因此很多场景不需要 .camel。原文的 view-Box:viewBox 示例没有真正展示该 modifier,应以 :view-box.camel 为准。

3. .attr(Vue 3)

Vue 3 支持 .attr,用于强制设置 HTML attribute:

<div :aria-label.attr="label"></div>

具体元素属性在 Vue 中有默认判断逻辑,.prop.attr 适合需要明确指定行为的场景。

八、.sync:Vue 2 与 Vue 3 的迁移

原文把 .sync 多处写成了 async。Vue 没有通用的 v-bind.async,正确名称是 .sync

Vue 2.7

<Child :title.sync="pageTitle" />

它大致等价于:

<Child
  :title="pageTitle"
  @update:title="pageTitle = $event"
/>

子组件需要发出对应事件:

this.$emit('update:title', newTitle)

使用 .sync 时:

  • 事件名必须是 update:<propName>
  • <propName> 必须与绑定的 prop 名一致;
  • 它不是任意 prop 的双向绑定;
  • 不要把 .sync 和复杂表达式混在一起;
  • 在字面量对象上使用 v-bind.sync 容易产生难以理解的行为,应拆成明确 prop。

Vue 3.5

Vue 3 移除了 .sync,使用带参数的 v-model

<Child v-model:title="pageTitle" />

子组件声明 prop 并触发 update:title

<script setup lang="ts">
const props = defineProps<{
  title: string
}>()

const emit = defineEmits<{
  'update:title': [value: string]
}>()

function updateTitle(value: string) {
  emit('update:title', value)
}
</script>

Vue 3.4+(Vue 3.5.39 可用)还可以使用 defineModel

<script setup lang="ts">
const title = defineModel<string>('title', {
  required: true,
})
</script>

<template>
  <input v-model="title" />
</template>

参考:Vue 3 Component v-modelVue 3 v-model 迁移

九、组件 v-model 的修饰符与版本差异

Vue 2 默认协议

<LegacyInput v-model="title" />

默认相当于:

<LegacyInput
  :value="title"
  @input="title = $event"
/>

Vue 2 可以通过 model 选项改变 prop 和事件名:

export default {
  model: {
    prop: 'checked',
    event: 'change',
  },
  props: {
    checked: Boolean,
  },
}

Vue 3 默认协议

<ModernInput v-model="title" />

默认相当于:

<ModernInput
  :modelValue="title"
  @update:modelValue="title = $event"
/>

多个模型可以写成:

<Editor
  v-model:title="title"
  v-model:content="content"
/>

.trim.number 等组件模型修饰符需要由子组件显式决定如何处理;在 Vue 3.4+ 可以使用 defineModel 的第二个返回值或 get/set 选项实现自定义转换。

十、常见修饰符对照表

修饰符Vue 2.7.16Vue 3.5.39作用/迁移说明
.lazy支持支持v-model 在 change 时同步
.trim支持支持去除两端空白
.number支持支持尝试转换为 number
.stop支持支持阻止冒泡
.prevent支持支持阻止默认行为
.self支持支持只处理 target 为自身的事件
.capture支持支持捕获阶段监听
.once支持支持监听器只执行一次
.passive支持支持passive: true,不能与 prevent 同用
.left/.right/.middle支持支持鼠标按钮过滤
.enter 等按键别名支持支持推荐写法
数字 keyCode历史支持移除Vue 3 使用按键名或 event.key
.ctrl/.alt/.shift/.meta支持支持系统修饰键
.exact支持支持限制系统修饰键组合
.prop支持支持强制 DOM property
.camel支持支持属性名大小写转换
.attr不作为常用 2.x API支持强制 HTML attribute
.native支持组件根原生事件移除Vue 3 使用 emits/fallthrough
.sync支持 2.3+移除Vue 3 使用 v-model:prop

十一、实际使用建议

  • 修饰符顺序会改变生成代码顺序,selfpreventstop 组合时要读懂语义;
  • .passive.prevent 不要同时使用;
  • Vue 3 新代码不要使用 .native、数字 keyCode 和 .sync
  • 组件事件应通过 defineEmits / $emit 明确声明;
  • 不要用 .prop 代替数据安全或属性校验;
  • v-model 修饰符只解决同步和转换细节,表单校验仍需单独处理;
  • 对键盘无障碍交互,不要只监听鼠标事件,也不要只依赖数字 keyCode;
  • 复杂滚动监听需要考虑节流、requestAnimationFrame 和 passive,而不仅仅是添加 .passive

十二、总结

  • .lazy.trim.number 是表单 v-model 修饰符;
  • .stop 阻止冒泡,.prevent 阻止默认行为,.self 过滤事件目标;
  • .once.capture.passive 影响监听器行为,其中 .passive 不是 .lazy
  • .enter 等按键别名比数字 keyCode 更可靠,Vue 3 已移除数字 keyCode;
  • .prop 操作 DOM property,.attr 操作 HTML attribute,.camel 处理属性命名;
  • Vue 2 的 .native.sync 需要单列为历史边界,Vue 3 分别使用事件 fallthrough/emitsv-model:prop
  • 修饰符只是语法辅助,事件传播、浏览器默认行为、组件 emits 和 DOM property/attribute 的概念仍要分别理解。

官方参考

Vue 2

Vue 3

原文出处

作者:CoderBin

来源:稀土掘金

本文保留原文的常见修饰符总结,并补充 Vue 2.7.16 与 Vue 3.5.39 的 API 版本边界。

457 DOCUMENTS · 10 COLLECTIONS
ARCHIVE SEARCH457 篇文章

SEARCH GUIDE

输入关键词开始搜索

支持搜索文章标题、所属分类和原始文档路径。

按分类浏览

10 COLLECTIONS