Vue项目中,子组件调用父组件方法示例,以及如何传值示例,对比使用插槽和不使用插槽区别

在 Vue 项目中,子组件调用父组件方法是一个常见的通信需求。Vue 提供了多种方式实现这一点,最主流的有:

  • 通过 props 传递回调函数
  • 通过 $emit 触发自定义事件(推荐)
  • 使用插槽(Slots)进行内容与逻辑解耦

下面将分别给出 不使用插槽使用插槽 的完整示例,并对比它们的区别。


✅ 一、不使用插槽:子组件调用父组件方法(两种方式)

方式1:通过 $emit(官方推荐)

子组件触发事件 → 父组件监听并执行方法

父组件 Parent.vue
vue 复制代码
<template>
  <div>
    <h2>父组件</h2>
    <p>当前计数:{{ count }}</p>
    <Child @increment="handleIncrement" />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import Child from './Child.vue'

const count = ref(0)

const handleIncrement = (step) => {
  count.value += step
}
</script>
子组件 Child.vue
vue 复制代码
<template>
  <button @click="sendToParent">点击 +2(通过 $emit)</button>
</template>

<script setup>
const emit = defineEmits(['increment'])

const sendToParent = () => {
  emit('increment', 2) // 向父组件传值 2
}
</script>

方式2:通过 props 传递函数

父组件把方法作为 prop 传给子组件 → 子组件直接调用

父组件 Parent.vue
vue 复制代码
<template>
  <div>
    <h2>父组件</h2>
    <p>当前计数:{{ count }}</p>
    <Child :on-increment="handleIncrement" />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import Child from './Child2.vue'

const count = ref(0)

const handleIncrement = (step) => {
  count.value += step
}
</script>
子组件 Child2.vue
vue 复制代码
<template>
  <button @click="callParent">点击 +3(通过 props 回调)</button>
</template>

<script setup>
const props = defineProps({
  onIncrement: {
    type: Function,
    required: true
  }
})

const callParent = () => {
  props.onIncrement(3) // 直接调用父组件方法并传参
}
</script>

✅ 二、使用插槽(Slots)的方式

插槽本身 不直接用于"调用父组件方法" ,但可以 让父组件在插槽内容中绑定自己的方法,从而实现更灵活的交互。

场景:模态框(Modal)组件,按钮由父组件提供

子组件 Modal.vue(使用默认插槽)
vue 复制代码
<template>
  <div class="modal" v-if="visible">
    <div class="content">
      <slot></slot> <!-- 父组件传入的内容 -->
    </div>
    <button @click="close">关闭</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const visible = ref(true)

const close = () => {
  visible.value = false
}

// 如果需要父组件控制显隐,也可暴露方法
defineExpose({ show: () => visible.value = true })
</script>
父组件 Parent.vue
vue 复制代码
<template>
  <div>
    <h2>使用插槽的模态框</h2>
    <Modal>
      <!-- 插槽内容由父组件定义,可自由绑定自己的方法 -->
      <p>这是模态框内容</p>
      <button @click="parentMethod">点击调用父组件方法!</button>
    </Modal>
  </div>
</template>

<script setup>
import Modal from './Modal.vue'

const parentMethod = () => {
  alert('我是父组件的方法!')
}
</script>

✅ 此时,"调用父组件方法"的逻辑完全由父组件在插槽中控制,子组件无需知道具体行为。


🔍 三、对比:使用插槽 vs 不使用插槽

对比维度 不使用插槽(props / emit) 使用插槽
职责分离 子组件需明确知道要调用哪个方法或事件 子组件只提供"容器",逻辑由父组件注入
灵活性 较低:交互逻辑写死在子组件中 极高:父组件可任意定制插槽内容和行为
复用性 适合固定行为的组件(如按钮、输入框) 适合结构固定但内容多变的组件(如卡片、弹窗、表格行)
代码量 简单场景代码少 需要 <slot> 标签,但减少 props 类型定义
性能 正常 更优(插槽内容按需渲染,避免无谓 props 传递)
适用场景 表单提交、简单交互 UI 容器类组件(Modal、Card、List、Layout)

✅ 总结建议

  • **优先使用 **$emit 实现子 → 父通信(符合 Vue 单向数据流理念)。
  • 当子组件是"UI 容器" (如弹窗、卡片、布局),且内容/行为高度可变时,强烈推荐使用插槽
  • 避免滥用 props 传函数,除非你明确需要类似 React 的回调模式(如高阶组件)。
  • 不要用 $refs 调用父方法(反模式,破坏封装性)。

相关推荐
Hilaku5 分钟前
作为面试官,我最怕遇到什么样的候选人?
前端·javascript·程序员
一 乐6 分钟前
自习室座位预约管理系统|基于springboot + vue自习室座位预约管理系统(源码+数据库+文档)
java·vue.js·spring boot
TiDi29 分钟前
Pinia优化重复请求
前端
web3d5201 小时前
01-用 Leafletjs 10 分钟搭一张水利一张图(Vue3 + Vite 实战)
前端·javascript
晚安日记wanna1 小时前
Vue2 的 defineProperty 差在哪四层追问筛掉九成候选人
前端·vue.js·面试
TiDi1 小时前
吸顶导航交互实现
前端
kisshyshy1 小时前
从Props透传到自定义Hook:系统梳理React跨层级通信与逻辑复用
前端·架构·代码规范
yume_sibai1 小时前
05-Flutter实战项目
前端·flutter
涛涛ing1 小时前
React 19.3 发布,但真正的赢家是 StyleX:当 AI 成为框架的“第一用户”
前端
zhangminghuan2 小时前
Vue vs React 实战拓展面试题|摒弃基础八股,聚焦业务开发核心难点(2026前端进阶)
前端