当前位置: 首页 > ds >正文

Vue基础知识-脚手架开发-子传父(props回调函数实现和自定义事件实现)

一、项目概况与结构

本文通过「App 父组件」+「School 子组件」+「Student 子组件」演示两种子传父方式:

  • School 组件:用「props 回调函数」传递学校名称(北京大学)给 父App;
  • Student 组件:用「自定义事件」传递学生名称(张三)给 父App,同时演示事件解绑;
  • App 组件:作为父组件,接收并展示子组件传递的数据。

项目结构(Vue 2 标准结构):

src/
├─ components/       # 子组件目录
│  ├─ School.vue     # props回调演示
│  └─ Student.vue    # 自定义事件演示
├─ App.vue           # 父组件(整合子组件)
└─ main.js           # 入口文件(初始化Vue)

二、完整代码实现

1. 入口文件:main.js


import Vue from 'vue'import App from './App.vue'Vue.config.productionTip = falsenew Vue({render: h => h(App),
}).$mount('#app')

2. 子组件 1:School.vue(props 回调函数实现子传父)

核心逻辑:父组件传递一个回调函数给子组件(通过 props),子组件调用该函数并传入数据,父组件在回调中接收数据。

<template><div class="demo"><h2>学校名称:{{name}}</h2><input type="button" value="传递学校名(props实现)" @click="sendSchoolName()" /></div>
</template>
<script>export default {name:'School',data(){return {name:'北京大学'}},props:['getSchoolName'],methods:{sendSchoolName(){this.getSchoolName(this.name)}}}
</script><style scoped>.demo{background-color: red;padding:10px;}
</style>

3. 子组件 2:Student.vue(自定义事件实现子传父)

核心逻辑:父组件给子组件绑定自定义事件,子组件通过this.$emit('事件名', 数据)触发事件,父组件在事件回调中接收数据;同时演示事件解绑(this.$off)。

<template><div class="demo"><h2>学生名称:{{name}}</h2><input type="button" value="传递学生名(自定义事件实现)" @click="sendStudentlName" /><input type="button" value="解绑自定义事件" @click="unbind" /></div>
</template>
<script>export default { name:'Student',data(){return {name:'张三'}},methods:{sendStudentlName(){//触发自定义事件@getStudentName,并传入参数this.$emit('getStudentName',this.name)},unbind(){//解绑一个this.$off('getStudentName')//解绑多个this.$off(['getStudentName','xx'])//解绑所有this.$off()}}}
</script><style scoped>.demo{background-color: orange;padding: 10px;margin-top: 30px;}
</style>

4. 父组件:App.vue(接收子组件数据)

作为父组件,分别用两种方式接收子组件数据,并展示结果;同时演示自定义事件的 “手动绑定” 和@click.native的用法。

<template><div class="app"><h2>学校名称:{{schoolName}}</h2><h2>学生名称:{{studentlName}}</h2><!--使用props实现子传父:父传回调函数getSchoolName给子调用。本质调父的getSchoolName(子写props接收并调用)--><School :getSchoolName="getSchoolName"/><!--使用自定义事件实现子传父:父给子绑定自定义事件并由子来触发。(子写this.$emit('',args[])触发自定义事件)--><!--  第一种实现:直接绑定(@用于组件上)。当Student实例触发@getStudentName事件,getStudentName调用。要求触发一次:@getStudentName加上.once即可<Student @getStudentName="getStudentName"/>--><!--  第二种实现:手动绑定。--><Student ref="student"/><!-- 注:<Student @click.native="nativeClick"/>@click.native表示单击事件(最终绑定在Student组件里template的根div)。不加native会被当作自定义事件。 --></div>
</template><script>import School from './components/School'  import Student from './components/Student';    export default {name:'App',data() {return {schoolName:'',studentlName:''}},components:{School,Student},methods:{getSchoolName(schoolName){this.schoolName = schoolName},getStudentName(studentlName){this.studentlName = studentlName},nativeClick(){alert('原生事件')}},mounted(){/* 第二种实现,手动绑定:当Student实例触发@getStudentName事件,getStudentName调用。要求触发一次:this.$refs.student.$once('getSstudentName',this.getStudentName) */this.$refs.student.$on('getStudentName',this.getStudentName)/* 写生匿名函数注意this指向问题:下面的this指向App组件,若不写箭头函数则this指向Student组件导致错误。this.$refs.student.$on('getStudentName',(studentlName)=>{this.studentlName = studentlName})  */}}
</script><style>.app{background-color: gray;padding: 10px;}</style>

三、核心知识点深度解析

1. 方式一:props 回调函数实现子传父

原理

父组件定义一个 “接收数据的回调函数”,通过props将该函数传递给子组件;子组件调用这个回调函数时,将内部数据作为参数传入,父组件在回调中拿到数据并更新自身状态。

关键步骤(3 步)
  1. 父组件定义回调函数:如getSchoolName(schoolName) { this.schoolName = schoolName }
  2. 父传子:通过 props 传递回调<School :getSchoolName="getSchoolName" />
  3. 子传父:调用回调函数传数据:子组件props: ['getSchoolName']接收,this.getSchoolName(this.name)触发传递。
优缺点
  • 优点:逻辑简单,代码量少,适合 “一次性传递” 或 “简单场景”;
  • 缺点:不支持事件解绑,若子组件多次触发,父组件无法主动停止接收;且 props 本质是 “数据传递”,用它传函数不符合 “props 仅传数据” 的设计初衷(语义化稍差)。

2. 方式二:自定义事件实现子传父

原理

Vue 组件实例自带事件系统($on绑定、$emit触发、$off解绑),父组件给子组件绑定一个 “自定义事件”,子组件通过$emit触发该事件并传递数据,父组件在事件回调中接收数据;可通过$off主动解绑事件,避免内存泄漏。

两种绑定方式(灵活选择)
绑定方式语法示例适用场景
模板直接绑定<Student @getStudentName="getStudentName" />简单场景,推荐优先使用
手动绑定($refs)this.$refs.studentRef.$on('事件名', 回调)需动态绑定 / 解绑(如条件绑定)
事件解绑(3 种场景)
  • 解绑单个事件:this.$off('事件名')(如 Student 组件的this.$off('getStudentName'));
  • 解绑多个事件:this.$off(['事件1', '事件2'])
  • 解绑所有事件:this.$off()(谨慎使用,会解绑组件所有自定义事件)。
优缺点
  • 优点:语义化清晰(专门用于 “事件通信”),支持绑定 / 解绑,适合 “多次触发” 或 “需要动态控制” 的场景;
  • 缺点:代码量略多,需理解 Vue 组件的事件系统($on/$emit/$off)。

3. 补充:@click.native 的作用

在组件标签上用@click时,Vue 默认将其视为 “自定义事件”(需子组件$emit('click')才触发);若想绑定组件根 DOM 的原生 click 事件,需加native修饰符:

  • 错误用法:<Student @click="handleClick" />(子组件需$emit('click')才触发);
  • 正确用法:<Student @click.native="handleClick" />(直接绑定子组件根 DOM 的原生 click 事件,无需子组件处理)。

原理native修饰符会 “穿透组件”,将事件绑定到子组件的根 DOM 元素上,本质是监听原生 DOM 事件(如clickinput)。

四、两种子传父方式对比总结

对比维度props 回调函数自定义事件
实现原理父传回调函数,子调用传参父绑定事件,子 $emit 触发传参
绑定方式仅模板绑定(:props="回调")模板绑定(@事件名)/ 手动绑定(refs.on)
事件解绑❌ 不支持✅ 支持($off)
触发次数控制❌ 无(子组件可无限次调用)✅ 支持单次触发($once)
语义化稍差(props 本应传数据,而非函数)优(专门用于事件通信)
适用场景简单场景、一次性传递(如初始化数据)复杂场景、多次触发、需解绑(如交互操作)
代码复杂度低(3 步完成)中(需理解事件 API)

五、注意事项

  1. 单向数据流:无论哪种方式,都遵循 Vue “单向数据流” 原则 —— 子组件仅传递数据,不直接修改父组件数据;父组件接收数据后自行更新,确保数据流向可追溯。
  2. 事件名大小写:自定义事件名推荐用 “kebab-case”(短横线命名),如get-student-name,避免用 “camelCase”(驼峰命名)(Vue 模板中不区分大小写,可能导致事件名匹配失败)。
  3. 手动绑定时机:通过$refs手动绑定事件时,需在mounted钩子中执行(确保子组件已挂载,$refs能获取到组件实例),避免在created中执行(此时子组件未渲染,$refsundefined)。
  4. 内存泄漏:若子组件是 “动态渲染”(如v-if控制显示隐藏),建议在组件卸载前用$off解绑事件,避免事件残留导致内存泄漏。

六、总结

Vue 子传父的两种方式各有适用场景:

  • 简单场景(如一次性传递初始化数据):优先用props 回调函数,代码简洁;
  • 复杂场景(如多次交互、需动态解绑):优先用自定义事件,语义化清晰且灵活。

无论选择哪种方式,核心都是遵循 “单向数据流”,让父组件统一管理数据,确保项目后期可维护性。

http://www.xdnf.cn/news/20135.html

相关文章:

  • Win11 解决访问网站525 问题 .
  • 【RK3576】【Android14】如何在Android kernel-6.1 的版本中添加一个ko驱动并编译出来?
  • Django 常用功能完全指南:从核心基础到高级实战
  • [光学原理与应用-401]:设计 - 深紫外皮秒脉冲激光器 - 元件 - 布拉格衍射在深紫外皮秒声光调制器(AOM)中的核心作用与系统实现
  • 小程序:12亿用户的入口,企业数字化的先锋军
  • Linux编程——网络编程(UDP)
  • 计算机网络模型入门指南:分层原理与各层作用
  • 对接旅游行业安全需求:旅游安全急救实训室的功能构建与育人目标
  • 网络安全初级-渗透测试
  • 用AI做TikTok影视解说,全流程全自动成片,不懂外语也能做全球矩阵!
  • 办公任务分发项目 laravel vue mysql 第一章:核心功能构建 API
  • 系统越拆越乱?你可能误解了微服务的本质!
  • 【Linux系统】线程同步
  • 正则表达式与转义符的区别。注意输入的东西经过了一次转义,一次正则表达式。\\转义是单斜杠\\在正则表达式也是单斜杠所以\\\\经过两道门才是字符单斜杠
  • MongoDB Change Streams:实时监听数据变化的实战场景
  • clickhouse迁移工具clickhouse-copier
  • Python EXCEL 小技巧:最快重新排列dataframe函数
  • 工业机器人标杆的数字化突围,珞石机器人如何以CRM实现业务重塑
  • 技术视界 | 跨域机器人通信与智能系统:打破壁垒的开源探索
  • 【Linux】环境变量与程序地址空间详解
  • ansible-角色
  • MySQL知识
  • 【C++】17. AVL树实现
  • 探索未来智能自动化,一个强大的自动化引擎
  • 苹果Vision Air蓝图或定档2027,三星/微美全息加速XR+AI核心生态布局卡位
  • 第二阶段WinForm-13:图表控件,N层架构,Dapper
  • 【数学建模学习笔记】机器学习分类:决策树分类
  • 团队协作与接口联调 Charles抓包工具在多人开发中的高效应用
  • WEBSTORM前端 —— 第4章:JavaScript —— 第7节:函数
  • 安徽造价信息网期刊及工程材料信息价