阿卡不拉阿卡不拉
Vue3
阿卡的博客
Vue3
阿卡的博客
  • Vue3

    • 快速入门

      • 搭建工程 👌
      • 模板语法
      • 响应式基础
      • 响应式常用 API
      • 计算属性
      • 类与样式绑定
      • 条件和列表渲染
      • 事件处理
      • 表单处理
      • 生命周期
      • 侦听器
      • 组件介绍
      • Props
      • 自定义事件
      • 组件v-model
      • 插槽
      • 前端路由介绍
      • KeepAlive内置组件
      • 状态管理库
      • 组件库介绍
    • 深入本质

      • 虚拟DOM本质
      • 模板的本质
      • 组件树和虚拟DOM树
      • 数据拦截的本质
      • 响应式数据的本质
      • 响应式的本质
      • 响应式和组件渲染
      • 实现响应式系统 1
      • 实现响应式系统 2
      • 图解EFFECT
      • 实现响应式系统 3
      • 手写computed
      • 手写watch
      • 指令的本质
      • 插槽的本质
      • v-model的本质
      • setup 语法标签
      • 组件生命周期
      • keepalive 生命周期
      • keepalive的本质
      • key的本质
    • 细节补充

      • 【Vue】属性透传
      • 【Vue】依赖注入
      • 【Vue】组合式函数 👌
      • 【Vue】自定义指令
      • 【Vue】插件
      • 【Vue】Transition
      • 【Vue】TransitionGroup
      • 【Vue】Teleport
      • 【Vue】异步组件
      • 【Vue】Suspense
      • 【Router】路由模式
      • 【Router】路由零碎知识
      • 【Router】路由匹配语法
      • 【Router】路由组件传参
      • 【Router】内置组件和函数
      • 【Router】导航守卫
      • 【Router】过渡特效
      • 【Router】滚动行为
      • 【Router】动态路由
      • 【State】通信方式总结
      • 【State】Pinia 自定义插件
      • 【场景】封装树形组件
      • 【场景】自定义 ref 实现防抖
      • 【场景】懒加载
      • 【场景】虚拟列表
      • 【场景】虚拟列表优化
      • 【第三方库】VueUse
      • 【第三方库】vuedragable
      • 【第三方库】vue-drag-resize
      • 【第三方库】vue-chartjs
      • 【第三方库】vuelidate
      • 【第三方库】vue3-lazyload
      • 【场景】Websocket 聊天室
      • 【Vite】✨ 认识 Vite👌
      • 【Vite】配置文件 👌
      • 【Vite】✨ 依赖预构建 👌
      • 【Vite】构建生产版本 👌
      • 【Vite】环境变量与模式
      • 【Vite】CLI
      • 【Vite】Vite 插件
  • 笔面试

    • HTML

      • HTML 面试题汇总
      • 文档声明
      • 语义化
      • W3C 标准组织
      • SEO
      • iframe
      • 微格式
      • 替换元素
      • 页面可见性
    • CSS

      • CSS 面试题汇总
      • CSS 单位总结
      • 居中方式总结
      • 隐藏元素方式总结
      • 浮动
      • 定位总结
      • BFC
      • CSS 属性计算过程
      • CSS 层叠继承规则总结
      • @import 指令
      • CSS3 calc 函数
      • CSS3 媒体查询
      • 过渡和动画事件
      • 渐进增强和优雅降级
      • CSS3 变形
      • 渐进式渲染
      • CSS 渲染性能优化
      • 层叠上下文
      • CSS3 遮罩
    • JavaScript

      • JavaScript 面试题汇总
      • ✨ let、var、const 的区别
      • JS中的数据类型
      • 包装类型
      • 数据类型的转换
      • 运算符
      • ✨ 原型链
      • ✨ this 指向
      • ✨ 垃圾回收与内存泄漏
      • ✨ 执行栈和执行上下文
      • ✨ 作用域和作用域链
      • ✨ 闭包
      • DOM 事件的注册和移除
      • DOM 事件的传播机制
      • 阻止事件默认行为
      • 递归
      • ✨ 属性描述符
      • class 和构造函数区别
      • 浮点数精度问题
      • 严格模式
      • ✨ 函数防抖和节流
      • ✨ WeakSet 和 WeakMap
      • ✨ 深浅拷贝
      • 函数柯里化
      • Node 事件循环
      • 尺寸和位置
    • 浏览器

      • 浏览器面试题汇总
      • ✨ 浏览器的渲染流程
      • ✨ 资源提示关键词
      • 浏览器的组成部分
      • IndexedDB
      • ✨ File API
      • ✨ 浏览器缓存
      • ✨ 浏览器跨标签页通信
      • Web Worker
    • 网络

      • 网络面试题汇总
      • 五层网络模型 👌
      • 常见请求方法 👌
      • ✨cookie👌
      • 面试题
      • 加密
      • ✨JWT👌
      • ✨ 同源策略及跨域问题 👌
      • 文件上传
      • ✨ 输入 url 地址之后
      • 文件下载
      • ✨ session
      • ✨ TCP
      • ✨ CSRF 攻击
      • ✨XSS 攻击 👌
      • ✨ 网络性能优化
      • 断点续传
      • 域名和 DNS
      • SSL、TLS、HTTPS 的关系
      • ✨ HTTP 各版本差异 👌
      • HTTP 缓存协议
      • ✨ WebSocket
    • 工程化

      • CMJ 和 ESM
      • npx
      • ESLint
    • Vue2

      • Vue 面试题汇总相关
      • 组件通信方式总结
      • 虚拟 DOM
      • v-model
      • 数据响应式原理
      • diff
      • 生命周期详解
      • computed
      • 过滤器
      • 作用域插槽
      • 过度和动画
      • 优化
      • keep-alive
      • 长列表优化
      • 其他 API
      • 模式和环境变量
      • 更多配置
      • 更多命令
      • 嵌套路由
      • 路由切换动画
    • Vue3

      • ✨ Vue3 整体变化 👌
      • ✨ Vue3 响应式变化 👌
      • ✨ nextTick 实现原理 👌
      • 两道代码题 👌
      • Vue 运行机制
      • 渲染器核心功能
      • 事件绑定与更新

事件处理

快速入门

在 Vue 中如果要给元素绑定事件,可以使用内置指令 v-on,使用该指定就可以绑定事件:

<template>
  <div>{{ count }}</div>
  <button v-on:click="add">+1</button>
</template>

<script setup>
import { ref } from 'vue'
const count = ref(0)
function add() {
  count.value++
}
</script>

<style scoped></style>

上面的事件示例非常简单,不过关于事件处理,有各种各样的细节。

事件处理各种细节

  1. 如果事件相关的处理比较简单,那么可以将事件处理器写成内连的
<template>
  <div>{{ count }}</div>
  <button v-on:click="count++">+1</button>
</template>

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<style scoped></style>

这种内连事件处理器用的比较少,仅在逻辑比较简单的时候可以快速完成事件的书写。

  1. 绑定事件是一个很常见的需求,因此 Vue 也提供了简写形式,通过 @ 符号就可以绑定事件
<button @click="count++">+1</button>

在日常开发中,更多的见到的就是简写形式。

  1. 向事件处理器传递参数
<template>
  <div>{{ count }}</div>
  <button @click="add('Hello World')">+1</button>
</template>

<script setup>
import { ref } from 'vue'
const count = ref(0)
function add(message) {
  count.value++
  console.log(message)
}
</script>

<style scoped></style>
  1. 事件对象
  • 没有传参:事件对象会作为一个额外的参数,自动传入到事件处理器,在事件处理器中,只需要在形参列表中声明一下即可
  • 如果有传参:这种情况下需要使用一个特殊的变量 $event 来向事件处理器传递事件对象
<template>
  <div>{{ count }}</div>
  <button @click="add">+1</button>
</template>

<script setup>
import { ref } from 'vue'
const count = ref(0)
// 事件对象会自动传入,直接在事件处理器的形参中声明即可
function add(event) {
  count.value++
  console.log(event)
  console.log(event.target)
  console.log(event.clientX, event.clientY)
}
</script>

<style scoped></style>
<template>
  <div>{{ count }}</div>
  <!-- 必须显式的使用 $event 来向事件处理器传递事件对象 -->
  <button @click="add('Hello World', $event)">+1</button>
</template>

<script setup>
import { ref } from 'vue'
const count = ref(0)
function add(message, event) {
  count.value++
  console.log(message)
  console.log(event)
  console.log(event.target)
  console.log(event.clientX, event.clientY)
}
</script>

<style scoped></style>

如果是箭头函数,写法如下:

<template>
  <div>{{ count }}</div>
  <!-- 如果是箭头函数,那么事件对象需要作为参数传入 -->
  <!-- 此时参数没有必须是 $event 的限制了 -->
  <button @click="(event) => add('Hello World', event)">+1</button>
</template>

<script setup>
import { ref } from 'vue'
const count = ref(0)
function add(message, event) {
  count.value++
  console.log(message)
  console.log(event)
  console.log(event.target)
  console.log(event.clientX, event.clientY)
}
</script>

<style scoped></style>

修饰符

之所以会有修饰符,是因为之前在书写原生事件处理的时候,事件处理器中经常会包含诸如阻止冒泡、阻止默认事件等非事件业务的逻辑。有了修饰符之后,可以使用事件修饰符来完成这些非核心的业务处理,让事件处理器更加专注于业务逻辑。

常见的事件处理器:

  • .stop:阻止事件冒泡
  • .prevent:阻止默认行为
  • .self:只有事件在该元素本身上触发时才触发处理函数(不是在子元素上)
  • .capture:改变事件的触发方式,使其在捕获阶段而不是冒泡阶段触发。
  • .once:事件只触发一次
  • .passive:用于提高页面滚动的性能。

修饰符的使用也很简单:

<button @click.stop="handleClick">点击我</button>

下面是一个具体的示例:

<template>
  <button @click.once="clickHandle">click</button>
</template>

<script setup>
function clickHandle() {
  console.log('你触发了事件')
}
</script>

<style scoped></style>

另外需要说一下,事件修饰符是可以连用的,例如现在有这么一个需求,我们希望用户在点击按钮时:

  • 阻止事件冒泡(.stop)。
  • 阻止默认行为(.prevent),例如,防止表单提交。
  • 在捕获阶段触发事件处理器(.capture),确保在任何可能的冒泡前响应。
  • 事件处理器只触发一次(.once)。
<button @click.capture.stop.prevent.once>click</button>

在连用事件修饰符的时候,修饰符的顺序通常不会影响最终的行为,因为不同的修饰符代表对不同方面的行为的控制,相互是不冲突的。

除了事件修饰符以外,Vue 还提供了一组按键修饰符,按键修饰符主要是用于检查特点的按钮:

  • .enter
  • .tab
  • .delete (捕获“Delete”和“Backspace”两个按键)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right
  • .ctrl
  • .alt
  • .shift
  • .meta(不同的系统对应不同的按键)
<template>
  <input type="text" @keyup.enter="submitText" />
</template>

<script setup>
function submitText() {
  console.log('你要提交输入的内容')
}
</script>

<style scoped></style>

按键修饰符也是能够连用,比如上面的例子,我们修改为 alt + enter 是提交

<input type="text" @keyup.alt.enter="submitText" />

Mac 系统中 alt 对应的是 option 按键

有一个特殊的修饰符 .exact ,exact 该单词的含义是“精确、精准” ,该修饰符的作用在于控制触发事件的时候,必须是指定的按键组合,不能够有其他按键。

<button @click.ctrl="onClick">A</button>

在上面的例子中,指定按下 ctrl 键触发事件,但是假设我现在同时按下 alt 和 ctrl 也会触发事件

<button @click.ctrl.exact="onClick">A</button>

添加了 .exact 修饰符之后,表示只有在按下 ctrl 并且没有按下其他按键的时候才会触发事件

最后还有三个鼠标按键修饰符,用于指定特定的鼠标按键:

  • .left
  • .right
  • .middle
<template>
  <button class="context-menu-button" @contextmenu.prevent.right="handleRightClick">
    右键点击
  </button>
</template>

<script setup>
function handleRightClick() {
  console.log('你点击了鼠标右键')
}
</script>

<style scoped>
.context-menu-button {
  padding: 10px 20px;
  cursor: context-menu; /* 显示适当的鼠标指针 */
  background-color: #f5f5f5;
  border: 1px solid #ccc;
  border-radius: 5px;
}
</style>
最近更新:: 2025/7/9 07:29
Contributors: AK
Prev
条件和列表渲染
Next
表单处理