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 调用父方法(反模式,破坏封装性)。

相关推荐
我是伪码农2 小时前
HTML和CSS复习
前端·css·html
林恒smileZAZ2 小时前
前端实现进度条
前端
前端老石人2 小时前
邂逅前端开发:从基础到实践的全景指南
开发语言·前端·html
阿珊和她的猫2 小时前
以用户为中心的前端性能指标解析
前端·javascript·css
木心术12 小时前
OpenClaw网页前端开发与优化全流程指南
前端·人工智能
Amumu121382 小时前
HTML5的新特性
前端·html·html5
SeSs IZED2 小时前
【Nginx 】Nginx 部署前端 vue 项目
前端·vue.js·nginx
成都渲染101云渲染66663 小时前
跳出“硬件堆砌”陷阱|渲染101如何用技术重构云渲染的专业价值?
java·前端·javascript
快乐点吧3 小时前
【前端】前端开发中如何高效利用 curl 工具
前端·状态模式