1. 主页 > 大智慧

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>

??重点圈起来要考:??

  1. 子组件必须用defineExpose暴露方法(Vue3新特性)
  2. 父组件用ref属性+value获取组件实例
  3. 方法调用像自家方法一样自然

(掏心窝子说)我去年在电商项目里翻过车:忘记写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
需要直接操控子组件???
需要传递多个参数???
符合单向数据流???
跨组件层级调用?配合事件总线

四、灵魂拷问:到底该用哪个?

(抓头发)我知道你们肯定要问:这俩货到底怎么选?说个我接私活的真实案例:

去年给健身房做预约系统,有个日期选择器子组件。父组件需要:

  1. 点「快速预约」按钮时自动选中明天日期(用ref直接调用子组件方法)
  2. 用户手动选择日期时触发数据更新(用emit传递新日期)

??个人经验法则:??

  • 像开关控制、强制校验这种「父组件主导」的操作用ref
  • 像表单提交、状态变更这种「子组件主动」的用emit
  • 遇到既要又要的情况可以混合使用(但别滥用)

五、常见坑位预警

  1. ??ref值为null??:
    (拍脑门)八成是子组件还没挂载完就调方法,用nextTick包裹调用:
javascript复制
import { nextTick } from 'vue'
nextTick(() => {
  formRef.value.validateForm()
})
  1. ??emit事件没响应??:
    检查事件名是否完全一致!Vue3强制要求大小写一致,@closeemit('Close')这种会失效

  2. ??TypeError报错??:
    八成是没写defineExpose,或者ref获取的是DOM元素而不是组件实例


六、说点得罪人的大实话

虽然ref用起来爽,但别滥用!有次我看同事代码,父子组件互相用ref调方法,跟麻花似的拧在一起。结果需求变更时,改一处崩三处(叹气)

??个人推荐原则:??

  • 能用emit解决的优先用emit
  • 需要反向操作时再用ref
  • 超过3层组件通信该上状态管理了
  • 记住:代码是给人看的,不是炫技的!

最后说句扎心的:别老想着找"最佳实践",适合项目阶段的方案才是好方案。新手期多用emit培养数据流意识,等业务复杂了再灵活搭配ref使用,这才是正道!

本文由嘻道妙招独家原创,未经允许,严禁转载