一、前言
上一篇解决了鼠标事件的"糖",这篇轮到键盘:搜索框敲回车触发搜索、Esc 关掉弹窗、Ctrl+S 保存草稿------这些交互全是按键修饰符的主场。配合鼠标左右中键修饰符,让事件处理彻底告别 if (e.key === ...) 的土味判断。
二、按键修饰符:把 e.key 写成后缀
原生监听回车键的土味写法 vs Vue 写法对比:
js
// 原生:先查文档找到 key 值,再比较字符串
function onKeyup(e) {
if (e.key === 'Enter') {
search()
}
}
vue
<!-- Vue:一个后缀完事 -->
<input @keyup.enter="search" />
常用按键别名表(直接当后缀用):
| 修饰符 | 对应按键 |
|---|---|
| .enter | 回车 |
| .tab | Tab |
| .delete | 退格 Backspace 和 删除 Delete |
| .esc | Esc |
| .space | 空格 |
| .up / .down / .left / .right | 方向键 |
keydown 和 keyup 都能用 :@keydown.enter、@keyup.esc 语义稍有差别(按下触发 vs 抬起触发),按交互感觉选。
三、系统修饰键:Ctrl+S 这类组合键
.ctrl / .alt / .shift / .meta 四个系统修饰键,可以组合叠加:
vue
<template>
<!-- Ctrl + S 保存(配合 .prevent 防止浏览器默认保存网页) -->
<input @keydown.ctrl.s.prevent="save" placeholder="按 Ctrl+S 试试" />
<!-- 多个组合:Ctrl + Shift + 清空 -->
<button @click.ctrl.shift="clearAll">Ctrl+Shift+点击 清空</button>
</template>
<script setup>
function save() {
console.log('保存草稿')
}
function clearAll() {
console.log('清空')
}
</script>
注意 .meta:Windows 上是 Win 键,Mac 上是 Cmd 键------跨平台快捷键用它,别写死 ctrl。
.exact:精确匹配,拒绝误触发
系统修饰符默认是"包含"关系:@click.ctrl 按着 Ctrl+Shift 点也会触发。加 .exact 要求"只按这些,多一个都不行":
vue
<!-- Ctrl 或按了更多键都触发 -->
<button @click.ctrl="open">宽松匹配</button>
<!-- 只有精确的 Ctrl 单键点击才触发 -->
<button @click.ctrl.exact="open">精确匹配</button>
四、没有别名的键:直接用 kebab-case 的 key 值
@keyup.page-down、@keyup.q 这类写法遵循一个规则:把 KeyboardEvent.key 的值转成 kebab-case:
vue
<template>
<!-- PageDown 键:key 值 "PageDown" → page-down -->
<input @keyup.page-down="nextPage" placeholder="按 PageDown 翻页" />
<!-- 字母键直接写小写 -->
<input @keyup.esc="close" placeholder="按 Esc 关闭" />
</template>
五、鼠标修饰符:左右中键
监听鼠标特定按键,和事件修饰符一样直接加后缀:
vue
<template>
<!-- 左键(默认) -->
<button @click="left">左键</button>
<!-- 右键:配合 .prevent 阻止浏览器菜单 -->
<div @contextmenu.prevent.right="showMenu">右键自定义菜单</div>
<!-- 中键 -->
<button @mousedown.middle="middle">中键按下</button>
</template>
实际开发最高频的用法是右键自定义菜单:@contextmenu.prevent 阻止系统菜单,再渲染自己的菜单弹层(配合 017 篇的 .stop 和 015 篇的 v-if)。
六、综合实战:搜索框 + 快捷键面板
回车搜索、Esc 清空、Ctrl+S 保存,三合一:
vue
<template>
<input
v-model.trim="keyword"
placeholder="输入后按 Enter 搜索,按 Esc 清空"
@keyup.enter="search"
@keyup.esc="reset"
/>
<p v-if="results.length">🔍 "{{ keyword }}" 的结果:{{ results.join('、') }}</p>
<p v-else>暂无搜索结果</p>
<textarea
v-model="draft"
placeholder="按 Ctrl+S 保存草稿"
@keydown.ctrl.s.prevent="saveDraft"
></textarea>
<p v-show="savedTip" class="tip">{{ savedTip }}</p>
</template>
<script setup>
import { ref } from 'vue'
const keyword = ref('')
const results = ref([])
const draft = ref('')
const savedTip = ref('')
function search() {
if (!keyword.value) return
results.value = [`结果1`, `结果2`, `结果3`]
}
function reset() {
keyword.value = ''
results.value = []
}
function saveDraft() {
localStorage.setItem('draft', draft.value)
savedTip.value = `✅ 已保存 ${new Date().toLocaleTimeString()}`
setTimeout(() => (savedTip.value = ''), 1500)
}
</script>
<style scoped>
.tip { color: #42b983; }
</style>
一行 @keyup.enter="search" 替代了原生的一堆 if 判断,事件处理逻辑全部收进方法里,模板保持声明式的清爽。
【截图位置:回车出结果、Esc 清空、Ctrl+S 出现保存提示的运行效果】
七、踩坑记录
- Vue3 移除了数字 keyCode :Vue2 的
@keyup.13彻底失效,只能用别名或 kebab-case 键值 - .delete 是两个键:退格和 Delete 都触发,做"删除字符"逻辑没问题,做"删除条目"要想清楚
- Mac 用户的 Ctrl :Mac 上 Cmd 是 .meta,写跨平台快捷键建议两个都绑:
@keydown.meta.s.prevent+@keydown.ctrl.s.prevent - 中文输入法下 keyup.enter 的坑:拼音候选期间按回车是"确认拼音"而非"确认搜索",严格场景要监听 compositionend 事件做过滤(先知道有这回事)
- 组合键误触发 :
@click.ctrl按住 Ctrl+A 再点也触发,要精确就配.exact - Ctrl+S 抢占 :不写
.prevent会弹出浏览器"保存网页"对话框,组合键覆盖浏览器默认行为时必须.prevent
八、今日小结
- 按键别名:.enter .esc .delete .tab .space .up/.down/.left/.right
- 系统修饰键 .ctrl/.alt/.shift/.meta + .exact 精确匹配
- 无别名按键:key 值转 kebab-case(page-down)
- 鼠标三键:.left / .right / .middle;覆盖浏览器默认行为记得 .prevent
下篇预告
指令篇的重头戏来了:表单双向绑定 v-model。input、textarea、select、checkbox、radio 全覆盖,顺便扒开它的真面目------其实只是 :value + @input 的语法糖。