React × Vue

children 与 slots

React 把嵌套内容作为 props.children 传递;Vue 通过默认、具名和作用域插槽组织内容出口。

核心结论

内容分发让容器组件负责结构,调用方负责具体内容。React 的嵌套 JSX 最终进入 children prop;Vue 用默认、具名和作用域 slot 把内容出口变成模板级协议。

组合流程

组件关系与数据流

ComponentContent OutletContent

差异焦点内容是父组件创建的 React 元素对象,并随 props 一起传递。

实线表示依赖、数据或命令传递,虚线表示事件、回调或清理路径。

flowchart TB
  accTitle: React children 与元素 prop
  accDescr: ReactDemo 在每次 render 中创建正文和按钮 React 元素,分别作为 children 与 footer prop 传给 ProfileCard,子组件直接把 props 放进自己的 JSX。
  parent["ReactDemo render"] --> elements[("创建 React elements")]
  elements -->|"children prop"| card["ProfileCard"]
  elements -->|"footer prop"| card
  card --> output[("组合后的元素树")]
  output -.->|"按钮事件更新父 state"| parent
  class parent,card component
  class elements,output resource
  classDef state fill:#fffdf8,stroke:#149eca,color:#25221d,stroke-width:1.2px
  classDef component fill:#e4f5fa,stroke:#149eca,color:#25221d,stroke-width:2px,font-weight:600
  classDef process fill:#f4fafb,stroke:#149eca,color:#25221d,stroke-width:1.6px
  classDef resource fill:#eee9df,stroke:#817a70,color:#25221d,stroke-width:1.4px

嵌套 JSX 最终也是 children prop,具名区域通常再设计一个普通 prop。

React 流程图
React 组件关系与数据流

滚轮缩放 · 按住拖动 · 双击重置 · Esc 关闭

组件关系与数据流

ComponentContent OutletContent

差异焦点插槽是模板级内容出口,具名和作用域能力由框架直接提供。

实线表示依赖、数据或命令传递,虚线表示事件、回调或清理路径。

flowchart TB
  accTitle: Vue 默认与具名插槽
  accDescr: VueDemo 模板为 default 和 footer 提供内容,编译器生成 slot functions,ProfileCard 渲染到 slot outlet 时调用对应函数。
  parent["VueDemo template"] --> slots[("default / footer slot functions")]
  slots --> outlet{{"ProfileCard 调用 slot outlets"}}
  outlet --> card["ProfileCard template"]
  card --> output[("组合后的 VNodes")]
  output -.->|"按钮事件修改父 ref"| parent
  class parent,card component
  class outlet process
  class slots,output resource
  classDef state fill:#fffdf8,stroke:#2f9d6b,color:#25221d,stroke-width:1.2px
  classDef component fill:#e4f4eb,stroke:#2f9d6b,color:#25221d,stroke-width:2px,font-weight:600
  classDef process fill:#f2f8f4,stroke:#2f9d6b,color:#25221d,stroke-width:1.6px
  classDef resource fill:#eee9df,stroke:#817a70,color:#25221d,stroke-width:1.4px

父模板提供插槽函数,子组件通过默认或具名 slot outlet 决定插入位置。

Vue 3 流程图
Vue 3 组件关系与数据流

滚轮缩放 · 按住拖动 · 双击重置 · Esc 关闭

完整 Demo 源码

以下代码直接读取在线 Demo 使用的源文件,没有省略或改写。

React 源码

import { useState } from "react";import { ProfileCard } from "./ProfileCard";export function ReactDemo() {  const [completed, setCompleted] = useState(3);  return (    <ProfileCard      title="本周学习进度"      footer={        <button          className="demo-button"          type="button"          onClick={() => setCompleted((current) => current + 1)}        >          完成一篇        </button>      }    >      <p>已经完成 {completed} 篇 React / Vue 对比笔记。</p>      <p className="demo-muted">正文作为 children,按钮作为 footer prop。</p>    </ProfileCard>  );}

Vue 3 源码

<script setup lang="ts">import { ref } from "vue";import ProfileCard from "./ProfileCard.vue";const completed = ref(3);</script><template>  <ProfileCard title="本周学习进度">    <p>已经完成 {{ completed }} 篇 React / Vue 对比笔记。</p>    <p class="demo-muted">正文进入默认插槽,按钮进入 footer 具名插槽。</p>    <template #footer>      <button class="demo-button" type="button" @click="completed += 1">        完成一篇      </button>    </template>  </ProfileCard></template>

在线观察

两个父组件向同一个卡片结构传入正文和底部操作。

React

children / footer prop

本周学习进度

已经完成 3 篇 React / Vue 对比笔记。

正文作为 children,按钮作为 footer prop。

Vue 3

default / footer slot

本周学习进度

已经完成 3 篇 React / Vue 对比笔记。

正文进入默认插槽,按钮进入 footer 具名插槽。

什么时候使用

需求ReactVue 3
单个主要内容区children默认 slot
多个具名区域元素 prop,如 footer具名 slot
子组件把数据交给内容模板render prop作用域 slot

内容分发解决“谁提供 UI”,普通数据和事件仍使用组件通信。