跳转到内容

children 与 slots

两个父组件都向同一个卡片结构传入正文和底部操作。React 传递 React 元素,Vue 模板则为不同的插槽出口提供内容。

React

嵌套内容作为 children,具名区域继续使用普通 prop。

在线预览

children / footer prop

本周学习进度

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

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

组件关系与数据流

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:#ffffff,stroke:#149eca,color:#172033,stroke-width:1.2px
  classDef component fill:#e5f6fb,stroke:#149eca,color:#172033,stroke-width:2px,font-weight:600
  classDef process fill:#f4fbfd,stroke:#149eca,color:#172033,stroke-width:1.6px
  classDef resource fill:#f3f5f8,stroke:#778195,color:#172033,stroke-width:1.4px

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

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

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

实际运行源码

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

默认和具名 slot 为模板提供不同的内容出口。

在线预览

default / footer slot

本周学习进度

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

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

组件关系与数据流

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:#ffffff,stroke:#42b883,color:#172033,stroke-width:1.2px
  classDef component fill:#e7f8f0,stroke:#42b883,color:#172033,stroke-width:2px,font-weight:600
  classDef process fill:#f2fbf7,stroke:#42b883,color:#172033,stroke-width:1.6px
  classDef resource fill:#f3f5f8,stroke:#778195,color:#172033,stroke-width:1.4px

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

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

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

实际运行源码

<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>