0

0

Vue 3 中子组件向父组件传递数据的正确方式

碧海醫心

碧海醫心

发布时间:2026-03-08 21:54:24

|

178人浏览过

|

来源于php中文网

原创

本文详解 Vue 3 中通过 emit 实现子→父通信的标准流程,纠正常见错误(如错误使用 v-on="$emit(...)"、插值位置不当、props 未传递等),并提供可运行的完整示例。

本文详解 vue 3 中通过 `emit` 实现子→父通信的标准流程,纠正常见错误(如错误使用 `v-on="$emit(...)"`、插值位置不当、props 未传递等),并提供可运行的完整示例。

在 Vue 3 的组件通信中,子组件向父组件传递数据必须依赖自定义事件(Custom Events),其核心机制是:子组件调用 this.$emit('eventName', payload) 触发事件,父组件通过 @eventName="handler" 监听并接收数据。但实践中常因语法误用或逻辑疏漏导致事件“看似触发却无响应”——正如问题中所述:console.log 显示子组件已成功 emit,但父组件方法未执行。根本原因往往不在逻辑本身,而在模板绑定方式。

✅ 正确的事件监听写法

子组件(Student.vue)中已正确定义并触发事件:

<script>
export default {
  emits: ["addStudent"], // 显式声明(推荐)
  methods: {
    addName() {
      console.log("Emitting:", this.name);
      this.$emit("addStudent", this.name); // ✅ 正确触发
    }
  }
}
</script>

而父组件中 绝对禁止 写成:

<!-- ❌ 错误:v-on="$emit(...)" 是无效语法,$emit 是实例方法,不能在模板中直接调用 -->
<Student v-on="$emit(receiveStudent)" />

✅ 正确写法是直接绑定事件名与处理函数:

立即学习前端免费学习笔记(深入)”;

<!-- 方式1:完整写法 -->
<Student @addStudent="receiveStudent" />

<!-- 方式2:等价简写(推荐) -->
<Student @addStudent="receiveStudent" />

? 提示:@addStudent 是 v-on:addStudent 的语法糖,它告诉 Vue —— 当 Student 组件内部触发 addStudent 事件时,立即执行父组件的 receiveStudent 方法,并将 emit 的参数自动传入。

行业贸易网站管理系统 2007 Beta 1
行业贸易网站管理系统 2007 Beta 1

1.修正BUG站用资源问题,优化程序2.增加关键词搜索3.修改报价4.修正BUG 水印问题5.修改上传方式6.彻底整合论坛,实现一站通7.彻底解决群发垃圾信息问题。注册会员等发垃圾邮件7.彻底解决数据库安全9.修改交易方式.增加网站担保,和直接交易两中10.全站可选生成html.和单独新闻生成html(需要装组建)11. 网站有10中颜色选择适合不同的行业不同的颜色12.修改竞价格排名方式13.修

下载

✅ 修复父组件模板中的其他关键错误

除事件绑定外,原父组件还存在两处典型错误,需同步修正:

  1. 文本插值 {{ students }} 位置错误
    插值表达式只能出现在标签内容区(content),不可置于开始标签内(如 )。若需调试显示数组,应放在语义合理的位置,例如:

    <pre class="brush:php;toolbar:false;">{{ JSON.stringify(students, null, 2) }}
  2. v-for 中未向子组件传递必要 props
    子组件声明了 props: ["Name", "Program"](注意命名风格建议用 camelCase,如 name, program),但父组件未传入任何 prop。这虽不阻止事件通信,但会导致子组件 props 始终为 undefined,且 v-for 渲染逻辑失效(当前 students 为空数组,循环不执行)。
    ✅ 正确做法(假设 students 是对象数组):

    <Student
      v-for="(student, index) in students"
      :key="index"
      :name="student.name"
      :program="student.program"
      @addStudent="receiveStudent"
    />

    ⚠️ 注意::key 应使用稳定唯一值(如 index 仅适用于简单静态列表;生产环境推荐用 student.id)。

✅ 完整可运行的父子组件示例

父组件 University.vue:

<template>
  <h2>Students Management</h2>
  <!-- 新增表单区域(可选) -->
  <Student @addStudent="receiveStudent" />

  <!-- 已有学生列表 -->
  <ul v-if="students.length">
    <li v-for="(student, index) in students" :key="index">
      {{ student.name }} ({{ student.program }})
      <button @click="deleteStudent(index)">Delete</button>
    </li>
  </ul>
  <p v-else>No students yet.</p>

  <!-- 调试输出 -->
  <details>
    <summary>Current students (debug)</summary>
    <pre class="brush:php;toolbar:false;">{{ JSON.stringify(students, null, 2) }}
<script> import Student from "./Student.vue"; export default { name: "University", components: { Student }, data() { return { students: [] }; }, methods: { receiveStudent(name) { console.log("✅ Received from child:", name); // ✅ 正确更新响应式数据 this.students.push({ name, program: "Undeclared" }); // 可扩展:保存到 localStorage 等 }, deleteStudent(index) { this.students.splice(index, 1); } } }; </script>

子组件 Student.vue(优化版):

<template>
  <div class="input-student">
    <input 
      type="text" 
      v-model="name" 
      placeholder="Enter student name" 
      @keyup.enter="addName"
    />
    <button @click="addName" class="submit-btn">Add Student</button>
  </div>
</template>

<script>
export default {
  name: "Student",
  emits: ["addStudent"], // Vue 3 推荐显式声明
  data() {
    return {
      name: ""
    };
  },
  methods: {
    addName() {
      if (this.name.trim()) {
        console.log("? Emitting student:", this.name);
        this.$emit("addStudent", this.name.trim());
        this.name = ""; // 清空输入框
      }
    }
  }
};
</script>

<style scoped>
.input-student {
  display: flex;
  flex-direction: column;
  width: 500px;
  margin: 20px auto;
  gap: 12px;
}
.submit-btn {
  padding: 8px 16px;
  background: #42b883;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
.submit-btn:hover {
  background: #36956a;
}
</style>

? 关键注意事项总结

  • 事件名一致性:子组件 emit("addStudent") 与父组件 @addStudent 必须完全一致(区分大小写);
  • emits 选项非必需但强烈推荐:Vue 3 中显式声明 emits 可提升类型安全与 IDE 支持,并避免被当作原生事件透传;
  • 避免在 v-for 中重复监听同一事件:每个 Student 实例应独立触发事件,父组件统一处理,而非为每个实例绑定不同 handler;
  • 响应式更新:确保在 receiveStudent 中通过 this.students.push(...) 等方式修改响应式数据,触发视图更新;
  • 调试技巧:在子组件 emit 前后加 console.log,在父组件 handler 开头加 console.log,双端验证数据流是否贯通。

遵循以上规范,即可实现稳定、可维护的 Vue 3 子→父通信。记住:事件是桥梁,@event="handler" 是桥墩,$emit 是过桥的车辆——三者缺一不可,且必须对齐方向。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
console接口是干嘛的
console接口是干嘛的

console接口是一种用于在计算机命令行或浏览器开发工具中输出信息的工具,提供了一种简单的方式来记录和查看应用程序的输出结果和调试信息。本专题为大家提供console接口相关的各种文章、以及下载和课程。

420

2023.08.08

console.log是什么
console.log是什么

console.log 是 javascript 函数,用于在浏览器控制台中输出信息,便于调试和故障排除。想了解更多console.log的相关内容,可以阅读本专题下面的文章。

541

2024.05.29

undefined是什么
undefined是什么

undefined是代表一个值或变量不存在或未定义的状态。它可以作为默认值来判断一个变量是否已经被赋值,也可以用于设置默认参数值。尽管在不同的编程语言中,undefined可能具有不同的含义和用法,但理解undefined的概念可以帮助我们更好地理解和编写程序。本专题为大家提供undefined相关的各种文章、以及下载和课程。

6433

2023.07.31

网页undefined是什么意思
网页undefined是什么意思

网页undefined是指页面出现了未知错误的意思,提示undefined一般是在开发网站的时候定义不正确或是转换不正确,或是找不到定义才会提示undefined未定义这个错误。想了解更多的相关内容,可以阅读本专题下面的文章。

3327

2024.08.14

网页undefined啥意思
网页undefined啥意思

本专题整合了undefined相关内容,阅读下面的文章了解更多详细内容。后续继续更新。

1621

2025.12.25

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

59

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

148

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

273

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

93

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue 教程
Vue 教程

共42课时 | 9.3万人学习

Vue3.x 工具篇--十天技能课堂
Vue3.x 工具篇--十天技能课堂

共26课时 | 1.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号