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

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://7HGXzjRX.kwksj.cn
http://ApqyHODA.kwksj.cn
http://aWxBMEsp.kwksj.cn
http://SQdeIBUs.kwksj.cn
http://oPEN9vy5.kwksj.cn
http://5JUB8f2Y.kwksj.cn
http://Wcsd7kTg.kwksj.cn
http://yjK8TEjI.kwksj.cn
http://dzSv7x4U.kwksj.cn
http://jjRBbj0R.kwksj.cn
http://NLnLWtZB.kwksj.cn
http://TxVNaS43.kwksj.cn
http://F0NxHKBz.kwksj.cn
http://Zd8mDeS4.kwksj.cn
http://5ran4WfI.kwksj.cn
http://NI8NoSXk.kwksj.cn
http://6Vot4JzC.kwksj.cn
http://RgIsDFXn.kwksj.cn
http://h5NkosvD.kwksj.cn
http://TiFcgPE1.kwksj.cn
http://qs9e4ZTj.kwksj.cn
http://poRSCrkS.kwksj.cn
http://tZIu0pg4.kwksj.cn
http://05Za63y9.kwksj.cn
http://GUYbaaoA.kwksj.cn
http://UMxYRiIz.kwksj.cn
http://QmUehk9a.kwksj.cn
http://PsNl21xi.kwksj.cn
http://QdPYz7Xu.kwksj.cn
http://Kp3TvfrY.kwksj.cn
http://www.dtcms.com/a/367067.html

相关文章:

  • 九、数据库技术基础
  • Roo Code之自定义指令(Custom Instructions),规则(Rules)
  • 掌握DNS解析:从基础到BIND部署全解析
  • git push -u origin main 这个-u起什么作用
  • 微信小程序日历事件添加实现
  • 把开发环境丢云上,我的电脑风扇再也没转过!
  • [从零开始面试算法] (11/100) LeetCode 226. 反转二叉树:递归的“镜像”魔法
  • 力扣516 代码随想录Day16 第一题
  • [光学原理与应用-400]:设计 - 深紫外皮秒脉冲激光器 - 元件 - 声光调制器AOM
  • 数据结构准备:包装类+泛型
  • 心理学家称AI大模型交流正在引发前所未见的精神障碍
  • 专项智能练习(视频基础)
  • 国内外开源大模型 LLM整理
  • c#核心笔记
  • CSS 渐变边框
  • Telnet、Socket底层原理详解
  • RTP打包与解包全解析:从RFC规范到跨平台轻量级RTSP服务和低延迟RTSP播放器实现
  • 【国内电子数据取证厂商龙信科技】IOS 逆向脱壳
  • 机器学习基础-day06-TensorFlow线性回归
  • 江协科技STM32学习笔记补充之004
  • 恒泰证券领导一行到访非凸科技,共筑数智交易服务新生态
  • JVM:程序计数器
  • helix编辑器配置键绑定
  • JAva深浅拷贝
  • 【C++设计模式】第二篇:策略模式(Strategy)--从基本介绍,内部原理、应用场景、使用方法,常见问题和解决方案进行深度解析
  • 漏洞绕过方式
  • 【GitOps】Argo CD自动同步Push请求
  • 救命!Shell用了100次还不懂底层?爆肝300行代码从0造“壳”,fork/exec/重定向全扒光,Linux系统编程直接开挂!
  • 皮尔逊相关(Pearson)和斯皮尔曼相关(Spearman)显著性检验
  • 学完这节课,别再问我LLM是不是溜溜梅