news 2026/5/26 13:26:28

Vue2 与 Vue3 自定义事件实现对比

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue2 与 Vue3 自定义事件实现对比

Vue2通过$emit触发事件,父组件使用@监听;


Vue3引入defineEmits()和emits选项显式声明事件,支持TypeScript类型检查。


主要差异:Vue3支持多v-model、移除.sync修饰符、提供事件验证,组合式API更灵活。


迁移时需注意移除$listeners、native修饰符,改用v-model:propName替代.sync。


Vue3事件系统更明确、类型安全,推荐使用defineEmits()声明事件。


Vue2 与 Vue3 自定义事件实现对比

一、Vue2 中的自定义事件

1. 子组件触发事件

vue

<template> <button @click="emitCustomEvent">触发事件</button> </template> <script> export default { methods: { emitCustomEvent() { // 触发自定义事件 this.$emit('custom-event', { message: '来自子组件的数据', timestamp: Date.now() }); // 触发带修饰符的事件 this.$emit('update:title', '新标题'); } } } </script>

2. 父组件监听事件

vue

<template> <div> <child-component @custom-event="handleCustomEvent" @update:title="title = $event" /> <p>收到消息: {{ message }}</p> <p>标题: {{ title }}</p> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { components: { ChildComponent }, data() { return { message: '', title: '原始标题' }; }, methods: { handleCustomEvent(payload) { this.message = payload.message; console.log('收到事件:', payload); } } } </script>

3. 使用 v-model 语法糖

vue

<!-- 子组件 --> <script> export default { model: { prop: 'value', event: 'change' }, props: ['value'], methods: { updateValue(newValue) { this.$emit('change', newValue); } } } </script> <!-- 父组件 --> <child-component v-model="dataValue" />

二、Vue3 中的自定义事件

1. Composition API 方式

vue

<template> <button @click="emitEvent">触发事件</button> </template> <script setup> import { defineEmits } from 'vue'; // 定义可触发的事件 const emit = defineEmits([ 'custom-event', 'update:title', 'change' // 用于 v-model ]); const emitEvent = () => { // 触发事件 emit('custom-event', { message: '来自子组件的数据', timestamp: Date.now() }); // 触发带修饰符的事件 emit('update:title', '新标题'); }; </script> <!-- 或者使用类型声明 --> <script setup lang="ts"> const emit = defineEmits<{ (e: 'custom-event', payload: { message: string, timestamp: number }): void (e: 'update:title', value: string): void (e: 'change', value: any): void }>(); </script>

2. Options API 方式

vue

<template> <button @click="emitEvent">触发事件</button> </template> <script> export default { emits: ['custom-event', 'update:title', 'change'], // 显式声明事件 // 或带验证 emits: { 'custom-event': (payload) => { return payload && typeof payload.message === 'string'; } }, methods: { emitEvent() { this.$emit('custom-event', { message: '数据', timestamp: Date.now() }); } } } </script>

3. 父组件监听事件

vue

<template> <div> <ChildComponent @custom-event="handleCustomEvent" @update:title="title = $event" v-model:title="title" <!-- Vue3 支持多个 v-model --> /> <p>收到消息: {{ message }}</p> <p>标题: {{ title }}</p> </div> </template> <script setup> import { ref } from 'vue'; import ChildComponent from './ChildComponent.vue'; const message = ref(''); const title = ref('原始标题'); const handleCustomEvent = (payload) => { message.value = payload.message; console.log('收到事件:', payload); }; </script>

三、主要差异对比

特性Vue2Vue3
事件定义不需要显式声明emits选项或defineEmits()
语法糖单个v-model多个v-model绑定
修饰符.sync修饰符内置v-model支持参数
组合式API不支持defineEmits()
类型支持有限完整的 TypeScript 支持
事件验证无内置验证支持事件参数验证

四、最佳实践示例

Vue3 完整示例

vue

<!-- CustomButton.vue --> <template> <button @click="handleClick"> <slot>点击我</slot> </button> </template> <script setup lang="ts"> interface EmitEvents { (e: 'click', event: MouseEvent): void (e: 'custom-click', payload: { id: number, value: string }): void (e: 'update:modelValue', value: boolean): void } const emit = defineEmits<EmitEvents>(); const handleClick = (event: MouseEvent) => { // 触发原生事件 emit('click', event); // 触发自定义事件 emit('custom-click', { id: 1, value: '按钮被点击' }); // 触发 v-model 更新 emit('update:modelValue', true); }; </script> <!-- 使用组件 --> <template> <CustomButton v-model="isActive" @custom-click="handleCustomClick" @click="handleNativeClick" /> </template>

事件验证示例

vue

<script> export default { emits: { // 验证提交事件 submit: (payload) => { // 必须返回布尔值表示验证是否通过 return ( payload && typeof payload.email === 'string' && payload.email.includes('@') && typeof payload.password === 'string' && payload.password.length >= 6 ); } }, methods: { handleSubmit() { const payload = { email: this.email, password: this.password }; // 验证失败会在控制台警告 this.$emit('submit', payload); } } } </script>

五、迁移注意事项

  1. .sync修饰符:Vue3 中已移除,使用v-model:propName替代

  2. $listeners:Vue3 中已移除,监听器直接作为$attrs的一部分

  3. 事件名大小写:Vue3 中推荐使用 kebab-case,但 camelCase 也能工作

  4. native 修饰符:Vue3 中已移除,所有事件都通过emits定义


Vue3 的事件系统更加明确和类型安全,推荐总是使用emits选项或defineEmits()来声明组件可以触发的事件。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/21 1:41:16

没N卡怎么学ResNet18?云端镜像开箱即用,3步出结果

没N卡怎么学ResNet18&#xff1f;云端镜像开箱即用&#xff0c;3步出结果 1. 为什么需要云端ResNet18学习环境&#xff1f; 作为一名编程培训班的老师&#xff0c;我经常遇到学生反映"本地电脑显卡太差跑不动深度学习模型"的问题。传统ResNet18教学面临三个典型痛点…

作者头像 李华
网站建设 2026/5/20 11:51:01

ResNet18图像分类实战:云端GPU 1块钱起体验

ResNet18图像分类实战&#xff1a;云端GPU 1块钱起体验 引言 作为一名计算机视觉方向的学生&#xff0c;你是否正在为毕业设计发愁&#xff1f;特别是当选题定为"猫狗图像分类"这类经典项目时&#xff0c;学校机房没有GPU权限&#xff0c;自己的笔记本跑大数据集又…

作者头像 李华
网站建设 2026/5/21 11:32:25

python 多进程apply_async、map_async、pool.imap的用法

想要系统掌握 Python 多进程模块multiprocessing.Pool中apply_async、map_async、imap这三个核心方法的使用语法、核心差异、适用场景和实战示例&#xff0c;从而根据实际需求选择合适的多进程并发方式&#xff0c;提升程序执行效率。前置基础在讲解这三个方法前&#xff0c;先…

作者头像 李华
网站建设 2026/5/21 5:40:17

ResNet18模型监控:低成本性能分析平台

ResNet18模型监控&#xff1a;低成本性能分析平台 引言 作为一名机器学习工程师&#xff08;MLE&#xff09;&#xff0c;你是否经常遇到这样的困扰&#xff1a;训练好的ResNet18模型部署后&#xff0c;需要持续监控其性能表现&#xff0c;但长期占用公司宝贵的GPU资源又显得…

作者头像 李华
网站建设 2026/5/22 19:46:50

基于AI的11项论文创作工具,支持LaTeX排版与内容优化

工具对比排名 工具名称 核心优势 支持LaTeX 适用场景 aibiye AIGC率降个位数&#xff0c;兼容知网规则 是 AI痕迹强处理 aicheck 学术改写优化&#xff0c;语义保留佳 是 格式统一化 askpaper 降重降AI一体&#xff0c;20分钟快速响应 是 初稿优化 秒篇 人类特…

作者头像 李华
网站建设 2026/5/20 18:20:26

JL — AC695X — 按键调试记录

本篇记录一下在开发按键中的遇到的一些问题&#xff1a; 业务需求是实现如下的按键功能&#xff1a;【AD按键】 蓝牙模式&#xff1a;按键序号单击长按长按保持KEY1模式切换开关机开关机KEY2上一曲音量-音量-KEY3下一曲音量音量KEY4空TWS连接断开空KEY5暂停/播放蓝牙连接/断开空…

作者头像 李华