Vue 事件机制全面解析:原生事件、自定义事件与 DOM 冒泡完全讲透

文章目录

  • [Vue 事件机制全面解析:原生事件、自定义事件与 DOM 冒泡完全讲透](#Vue 事件机制全面解析:原生事件、自定义事件与 DOM 冒泡完全讲透)
  • 1.Vue事件的核心机制
    • [1.1 原生事件(native events)](#1.1 原生事件(native events))
    • [1.2 子组件自定义事件(子组件 emit)](#1.2 子组件自定义事件(子组件 emit))
    • [1.3 浏览器 DOM 的事件冒泡机制](#1.3 浏览器 DOM 的事件冒泡机制)
  • 2.事件相关的实用补充
    • [2.4 DOM 常用事件](#2.4 DOM 常用事件)
    • [2.5 Vue 事件修饰符总览](#2.5 Vue 事件修饰符总览)

Vue 事件机制全面解析:原生事件、自定义事件与 DOM 冒泡完全讲透

为什么要理解 Vue 事件?

  • 只知道 @click,却分不清它属于谁

  • 子组件不 emit,父组件 @click 为何能触发?

  • 面试中被问 "emit 和 @click 区别?

1.Vue事件的核心机制

1.1 原生事件(native events)

当 @drop 写在 HTML 原生标签上,例如:

复制代码
<div @drop="handleDrop"></div>

这说明:

  • 监听的是浏览器 DOM 的 drop 事件
  • 用户把文件拖到 上时触发
  • 不需要任何子组件 emit

示例如下:

html 复制代码
<div
  class="chunk-upload-trigger"
  @drop="handleDrop"
  @dragenter="handleDragEnter"
  @dragleave="handleDragLeave"
>

这些都是原生 DOM 事件,没有任何"子组件触发"的概念

1.2 子组件自定义事件(子组件 emit)

父组件中写入:

html 复制代码
<Child @file-selected="onFileSelected" />

等待子组件 Child 调用

javascript 复制代码
emit('file-selected', file)

父组件收到这个事件并执行 onFileSelected

  • ChunkUploadTrigger 内部 emit('file-selected', file)
  • UploadPanel 接收到
  • 执行 handleFileSelected

这种完全不涉及 DOM 事件。

1.3 浏览器 DOM 的事件冒泡机制

父组件中

复制代码
<ChunkUploadTrigger @drop="handleDrop" />

子组件中

复制代码
<div @drop="handleDropInside"></div>

子组件不用 emit 通知父组件,子组件父组件都是同名的事件,此时父组件的事件就会穿透绑定到子组件根元素,两者的执行顺序,childDrop() 会触发,parentDrop() 也会触发,两者触发顺序按 DOM 事件流来(冒泡顺序)

DOM 事件冒泡不关心你是不是在一个文件、一个组件,它只关心 DOM 节点树。

复制代码
父组件根 DOM
  └── 子组件根 DOM
        └── 子组件内部 DOM

所以虽然写在了两个.vue 文件,但是渲染出来的其实是跟在一个文件里写了两个 父子div 没有任何区别,事件冒泡就是沿着这棵 DOM 树往上走的

复制代码
<Parent>
  <ChunkUploadTrigger />
</Parent>

<div class="parent-root">
  <div class="chunk-upload-trigger">   ← 子组件根节点
    <div>...</div>
  </div>
</div>

2.事件相关的实用补充

2.4 DOM 常用事件

浏览器原生事件,放在 HTML 标签上就能触发

鼠标事件

click,dblclick,mousedown,mouseup

键盘事件

keydown,keyup,keypress

输入 & 表单事件

dragenter,dragover,dragleave,drop

其他 DOM 事件

scroll,wheel,resize,load,error

2.5 Vue 事件修饰符总览

修饰符 含义 对应的 DOM 行为
.stop 阻止事件冒泡 event.stopPropagation()
.prevent 阻止默认行为 event.preventDefault()
.capture 使用捕获模式 addEventListener(..., true)
.self 只有事件目标是当前元素时触发 event.target === currentTarget
.once 事件只触发一次 自动 removeEventListener
.passive 表示监听器不会调用 preventDefault passive: true

比如:

html 复制代码
@dragover.prevent="handleDragOver"
相关推荐
良逍Ai出海3 分钟前
我用 Codex 搭了一个 WordPress 独立站
前端
TPBoreas4 分钟前
前端面试问题打把-场景题
开发语言·前端·javascript
问心无愧05134 分钟前
ctf show web入门159
前端·笔记
San813_LDD5 分钟前
[Vue/HTML]ECharts 使用指南:从入门到绘制各种常用图表
vue.js·html·echarts
恋猫de小郭9 分钟前
Flutter 又为 AI 时代添砖加瓦:全新 ComponentLibrary 提议
android·前端·flutter
就叫_这个吧11 分钟前
HTML或JSP页面链接CSS,link标签没问题,但不显示样式问题解决
java·前端·css·html·intellij-idea·jsp
IT_陈寒14 分钟前
SpringBoot这个坑差点让我加班到天亮
前端·人工智能·后端
小小龙学IT20 分钟前
Rust Web 框架 Axum:轻量级异步的下一代后端利器
前端·驱动开发·rust
大鱼前端23 分钟前
10 分钟用 Bun + Hono + SQLite 跑通一个全栈 API
前端·javascript
古怪今人29 分钟前
Vite8的项目中集成CSS预处理器编译器SCSS 集成Mock工具
前端·css·scss