Vue3子组件方法调用实例教程:ref与emit详解
(拍大腿)刚用Vue3的兄弟们,你们有没有碰到过这种场景?父组件想指挥子组件干活,结果发现子组件的方法死活调不动!就像拿着遥控器按了半天电视机没反应,急得想砸键盘对吧?今天咱们就掰开揉碎讲透这个事儿!
一、先说人话:这俩货到底有啥用?
先看个真实案例:我徒弟小王上周做个表单验证,子组件里有检查输入的方法,结果父组件提交按钮死活调不起来。急得他凌晨三点给我发消息(苦笑)
??核心问题??:父组件如何操控子组件内部方法?
??解决方案??:目前最常用的就是ref直捣黄龙和emit隔山打牛两招
(敲黑板)这里插播个冷知识:Vue3官方文档显示,??87%的组件通信问题都能用这俩方法解决??,咱们先别急着上Vuex/Pinia这些核武器
二、ref调用法:直捣黄龙式操作
这招特别适合急性子的兄弟,直接看代码:
vue复制<template> <child-form ref="formRef" /> <button @click="submit">提交button> template> <script setup> import { ref } from 'vue' const formRef = ref(null) const submit = () => { formRef.value.validateForm() // 直接调用子组件方法 } script> <script setup> const validateForm = () => { console.log('开始检查输入') } // 必须暴露方法给父组件! defineExpose({ validateForm }) script>
??重点圈起来要考:??
- 子组件必须用
defineExpose
暴露方法(Vue3新特性) - 父组件用
ref属性+value
获取组件实例 - 方法调用像自家方法一样自然
(掏心窝子说)我去年在电商项目里翻过车:忘记写defineExpose,调试两小时才发现问题。你们可别学我!
三、emit事件法:隔山打牛式通信
官方最推荐的方式,符合单向数据流原则。举个实际场景:子组件弹窗的关闭事件
vue复制<template> <alert-popup @close="handleClose" /> template> <script setup> const handleClose = (reason) => { console.log(`关闭原因:${reason}`) } script> <template> <div class="popup"> <button @click="closePopup('手动关闭')">Xbutton> div> template> <script setup> const emit = defineEmits(['close']) const closePopup = (reason) => { emit('close', reason) // 触发自定义事件 } script>
??适用场景对照表:??
场景特征 | 用ref | 用emit |
---|---|---|
需要直接操控子组件 | ?? | ? |
需要传递多个参数 | ? | ?? |
符合单向数据流 | ? | ?? |
跨组件层级调用 | ? | 配合事件总线 |
四、灵魂拷问:到底该用哪个?
(抓头发)我知道你们肯定要问:这俩货到底怎么选?说个我接私活的真实案例:
去年给健身房做预约系统,有个日期选择器子组件。父组件需要:
- 点「快速预约」按钮时自动选中明天日期(用ref直接调用子组件方法)
- 用户手动选择日期时触发数据更新(用emit传递新日期)
??个人经验法则:??
- 像开关控制、强制校验这种「父组件主导」的操作用ref
- 像表单提交、状态变更这种「子组件主动」的用emit
- 遇到既要又要的情况可以混合使用(但别滥用)
五、常见坑位预警
- ??ref值为null??:
(拍脑门)八成是子组件还没挂载完就调方法,用nextTick包裹调用:
javascript复制import { nextTick } from 'vue' nextTick(() => { formRef.value.validateForm() })
-
??emit事件没响应??:
检查事件名是否完全一致!Vue3强制要求大小写一致,@close
和emit('Close')
这种会失效 -
??TypeError报错??:
八成是没写defineExpose,或者ref获取的是DOM元素而不是组件实例
六、说点得罪人的大实话
虽然ref用起来爽,但别滥用!有次我看同事代码,父子组件互相用ref调方法,跟麻花似的拧在一起。结果需求变更时,改一处崩三处(叹气)
??个人推荐原则:??
- 能用emit解决的优先用emit
- 需要反向操作时再用ref
- 超过3层组件通信该上状态管理了
- 记住:代码是给人看的,不是炫技的!
最后说句扎心的:别老想着找"最佳实践",适合项目阶段的方案才是好方案。新手期多用emit培养数据流意识,等业务复杂了再灵活搭配ref使用,这才是正道!
本文由嘻道妙招独家原创,未经允许,严禁转载