news 2026/5/1 10:04:20

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/4/12 19:43:50

Vue 官方推荐:kebab-case(短横线命名法)

kebab-case&#xff08;短横线命名法&#xff09;是一种使用连字符连接小写单词的命名方式&#xff0c;Vue官方推荐在模板中使用。与camelCase&#xff08;驼峰式&#xff09;和snake_case&#xff08;蛇形命名&#xff09;不同&#xff0c;kebab-case在HTML中更具可读性和一致…

作者头像 李华
网站建设 2026/4/30 14:34:17

vLLM加持下的Qwen2.5-7B-Instruct:极致推理效率方案

vLLM加持下的Qwen2.5-7B-Instruct&#xff1a;极致推理效率方案 在大模型落地加速的今天&#xff0c;如何在有限算力条件下实现高吞吐、低延迟、长上下文支持的语言模型服务&#xff0c;已成为AI工程团队的核心挑战。尤其是在企业级应用中&#xff0c;面对并发请求、结构化输出…

作者头像 李华
网站建设 2026/5/1 9:00:16

ResNet18团队协作:5人共享GPU资源,实时查看彼此进度

ResNet18团队协作&#xff1a;5人共享GPU资源&#xff0c;实时查看彼此进度 引言 想象一下&#xff0c;你和4个小伙伴正在创业&#xff0c;大家都在用ResNet18开发不同的产品功能——有人做图像分类&#xff0c;有人搞目标检测&#xff0c;还有人研究迁移学习。这时候最头疼的…

作者头像 李华
网站建设 2026/5/1 9:00:15

实战Qwen2.5-7B-Instruct:结合vLLM加速模型推理

实战Qwen2.5-7B-Instruct&#xff1a;结合vLLM加速模型推理 一、引言&#xff1a;为何选择vLLM部署Qwen2.5-7B-Instruct&#xff1f; 在大语言模型&#xff08;LLM&#xff09;的落地实践中&#xff0c;推理效率与响应延迟是决定用户体验和系统吞吐量的关键因素。尽管Qwen2.5-7…

作者头像 李华
网站建设 2026/5/1 9:00:15

ResNet18物体识别3步上手:云端GPU免安装,新手友好

ResNet18物体识别3步上手&#xff1a;云端GPU免安装&#xff0c;新手友好 引言&#xff1a;不懂代码也能玩转AI物体识别 想象一下这样的场景&#xff1a;你正在整理公司产品库的海量图片&#xff0c;需要快速找出所有包含"水杯"的照片&#xff1b;或者你想自动统计…

作者头像 李华
网站建设 2026/5/1 6:54:56

AI万能分类器性能优化:降低延迟提升吞吐量的实战方法

AI万能分类器性能优化&#xff1a;降低延迟提升吞吐量的实战方法 1. 背景与挑战&#xff1a;零样本分类的高可用性需求 随着企业智能化升级加速&#xff0c;文本分类在工单系统、客服机器人、舆情监控等场景中扮演着核心角色。传统的有监督分类模型依赖大量标注数据和周期性训…

作者头像 李华