CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Vue 3 核心/课时/组件与 Props
RawBlame
课时目录12 节

Vue 3 核心

  1. 01Vue 是什么
  2. 02项目创建与 SFC
  3. 03模板语法
  4. 04响应式基础
  5. 05组件与 Props
  6. 06计算属性与侦听
  7. 07组合式 API 深入
  8. 08Vue Router
  9. 09Pinia 状态管理
  10. 10数据获取
  11. 11构建与部署
  12. 12综合练习

组件与 Props

父子通信、emit、slot。

35 分钟

组件与 Props

这一课你将能做到

  1. 拆分父子组件,用 props 向下传数、用 emit 向上发事件
  2. 使用具名/默认 slot 做布局插槽
  3. 对照 React:props 只读、子通知识父,思想一致、API 不同

为什么要学

单文件越写越长就要拆。拆分后:父管数据与流程,子管展示与局部交互。
本站 React 课同样强调单向数据流;Vue 用 props + emit + slot 表达。

先建立图像

父 ──props──▶ 子
父 ◀──emit─── 子
父在模板里写子标签时,子的 slot 位置被父填内容
通道方向人话
props父→子参数,子只读
emit子→父通知父「发生了某事」
slot父→子的坑位把模板片段塞进子

跟着做

步骤 1:子组件声明 props

<!-- TrackCard.vue -->
<script setup>
const props = defineProps({
  title: { type: String, required: true },
  level: { type: String, default: "beginner" },
});
</script>

<template>
  <article>
    <h2>{{ props.title }}</h2>
    <p>难度:{{ level }}</p>
  </article>
</template>

模板里可直接用 level(setup 已暴露)。defineProps 是编译期宏,无需 import。

步骤 2:父传入

<script setup>
import TrackCard from "./TrackCard.vue";
</script>

<template>
  <TrackCard title="Vue 3 核心" level="intermediate" />
</template>

步骤 3:子 emit,父处理

<!-- CounterBtn.vue -->
<script setup>
const emit = defineEmits(["inc"]);
</script>
<template>
  <button type="button" @click="emit('inc', 1)">加一</button>
</template>
<script setup>
import { ref } from "vue";
import CounterBtn from "./CounterBtn.vue";
const total = ref(0);
</script>
<template>
  <p>{{ total }}</p>
  <CounterBtn @inc="(n) => (total += n)" />
</template>

注意:模板里 total 是 ref 自动解包,total += n 可行;在纯 script 回调里记得 .value。

步骤 4:默认 slot

<!-- Panel.vue -->
<template>
  <section class="panel">
    <slot>默认内容</slot>
  </section>
</template>
<Panel>
  <p>侧栏说明</p>
</Panel>

步骤 5:具名 slot(布局)

<!-- Layout.vue -->
<template>
  <header><slot name="header" /></header>
  <main><slot /></main>
</template>
<Layout>
  <template #header><h1>CodeRoadMap</h1></template>
  <p>正文</p>
</Layout>

步骤 6:对照 React

VueReact
defineProps函数参数 props
emit('x') + @xonX 回调 props
<slot>children / 渲染 props

写三句笔记完成迁移。

讲清楚要点

  1. props 单向:子不要直接改 prop;要改就 emit 让父改源。
  2. 显式 emits 利于文档与校验,避免随意 $emit 拼写错误。
  3. 对象/数组 prop 仍是引用:子改内部字段会波及父——约定上仍应当只读,或解构到本地副本。
  4. slot 解决「父子都要定制中间 UI」:比层层 props 传 VNode 更符合模板思维。
  5. 组件名与文件名:一致更好找。
  6. 本站卡片列表:React 里 map 出卡片;Vue 同样 map/v-for 出子组件。

你可能会懵的地方

  • defineProps 返回值要不要接?
    模板只用 prop 名时可不接;在 script 里用再接 props。

  • camelCase vs kebab-case?
    DOM 模板里常用 kebab;SFC 模板两者多可。保持团队一致。

  • 透传 attributes?
    非 props 的属性默认落到根元素;进阶再挖 inheritAttrs。

  • provide/inject?
    跨多层传递;下一课之后、Context 对照时再系统用。本课先 props。

  • 循环引用组件?
    可能需异步组件;入门先避免环形依赖。

错法对照

错法问题正解
子改 prop单向流破坏、难追emit 通知父
事件名拼错父听不到defineEmits + 一致命名
巨型单文件难测按 UI 区块拆
slot 与 props 重复造同一数据API 混乱数据 props,结构 slot
无 key 的列表组件状态错乱v-for :key
把 Vue 组件塞进 React 树硬混运行时灾难分项目练习

自测三问

  1. 为什么说 props 是只读的?
  2. emit 相对「子直接改父的对象字段」好在哪?
  3. 默认 slot 与具名 slot 各适合什么?

小结一句话

组件用 props 向下、emit 向上、slot 填坑;保持单向数据流,拆分才可控。

动手加深

把本课「跟着做」再跑一遍,但这次故意先写出错法表里的一种写法,观察报错或错误现象 30 秒,再改回正解。
用自己的话补三条笔记:① 我最容易踩的坑;② 成功时屏幕/结果长什么样;③ 本课与上一课的衔接点。写不出来就重做步骤,不要只标完成。

官方延伸

  • 组件基础
  • Props
  • 下一课:计算属性与侦听
加载本节练习…
← 上一课响应式基础下一课 →计算属性与侦听