news 2026/6/2 1:26:07

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/31 13:54:18

ResNet18-CIFAR10一键运行:云端镜像开箱即用

ResNet18-CIFAR10一键运行&#xff1a;云端镜像开箱即用 引言&#xff1a;为什么选择云端镜像&#xff1f; 作为编程培训班的学员&#xff0c;你可能正在为ResNet18的作业发愁——50%的同学都卡在了环境配置环节。传统的本地安装需要配置Python环境、安装PyTorch、下载数据集…

作者头像 李华
网站建设 2026/5/28 14:59:05

从零部署Qwen2.5-7B-Instruct大模型|vLLM加速,Chainlit前端交互

从零部署Qwen2.5-7B-Instruct大模型&#xff5c;vLLM加速&#xff0c;Chainlit前端交互 引言&#xff1a;为什么选择 Qwen2.5 vLLM Chainlit 架构&#xff1f; 在当前大模型快速迭代的背景下&#xff0c;如何高效、低成本地将先进语言模型部署为可交互服务&#xff0c;成为…

作者头像 李华
网站建设 2026/5/28 13:59:29

ResNet18物体识别部署捷径:预置镜像免调试,省心省力

ResNet18物体识别部署捷径&#xff1a;预置镜像免调试&#xff0c;省心省力 引言 作为一名程序员&#xff0c;周末想用ResNet18做个有趣的物体识别项目&#xff0c;但最头疼的往往不是写代码&#xff0c;而是配环境——CUDA版本冲突、PyTorch安装报错、依赖库缺失...这些琐碎…

作者头像 李华
网站建设 2026/5/27 23:22:53

9个AI论文撰写解决方案,实现LaTeX自动化与文本润色

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

作者头像 李华
网站建设 2026/5/28 13:59:30

ResNet18物体识别新方案:云端GPU按秒计费,极致省钱

ResNet18物体识别新方案&#xff1a;云端GPU按秒计费&#xff0c;极致省钱 引言 作为一名精打细算的开发者&#xff0c;你是否遇到过这样的困扰&#xff1a;需要运行物体识别任务时&#xff0c;要么花大价钱购买昂贵的GPU设备&#xff0c;要么忍受公有云平台高昂的按小时计费…

作者头像 李华