本节摘要:组件如何被定义、注册进应用、再嵌套成一棵树,是组织代码的第一课。React 组件即函数、Vue 组件即单文件组件,两者的注册与嵌套套路虽有差别,但都指向"树越清晰越易维护"。本节把这两套流程对齐讲清。
本节阅读目标
阅读完本节,你应当能够:
把一个组件送上舞台,要过三个环节:
新手常常把"定义"当成"注册",于是引入没生效、标签找不到,问题多半出在漏了注册这一步。
React 里组件定义就是函数,用的地方直接写标签就完成一次"使用",本文件内部即注册:
// 定义子组件 function Badge({ text }) { return <span className="badge">{text}</span>; } // 在父组件里使用(个别局部注册即<Badge/>) function Card({ title }) { return ( <div className="card"> <h2>{title}</h2> <Badge text="NEW" /> </div> ); }
组件从 Card 到 Badge 构成父子嵌套,父组件能通过 props 往下喂数据,这是第 3.4 节单向数据流在组织维度的落地。
Vue 用单文件组件定义,在 script 里引入并注册,再在 template 里使用:
<!-- ChildBadge.vue --> <template><span class="badge">{{ text }}</span></template> <script setup> defineProps(['text']); </script> <!-- ParentCard.vue --> <template> <h2>{{ title }}</h2> <ChildBadge text="NEW" /> </template> <script setup lang="ts"> import ChildBadge from './ChildBadge.vue'; const title = '卡片'; </script>
script setup 里 import 进来的子组件自动注册,template 里可直接写标签。Vue 的"引入即登记"让大部分场景不再需要手动注册列表,省掉了一类常见错误。

三个高频坑:忘注册导致标签没渲染、导入路径写错导致的编译错、命名不一致让人找不到组件。都排查一遍能省很多调试时间。
注册有粒度之分:局部注册把组件挂在某个父组件名下,只在那一棵里可用;全局注册让组件处处可用,不用每个父组件都 import 一次。很多项目喜欢把"通用组件都全局注册",省 import 看似方便,代价却是:全局组件和全局样式一样,一旦滥用,"谁在用、改一处影响哪"变得难追踪,调试时得在全站翻。
比稿时的建议是:组件被多个完全不同家族的父组件用到、且语义高度通用,才考虑全局注册;多数"和某个功能绑定"的组件保持局部,父组件 import 它,来源一棵清楚。这份克制和你拒绝全局变量的理由同源——可见即可控的部分越少,项目越好维护。这与 5.4 节样式治理里"别滥用全局 CSS"是同一种分摊思想的延伸。
抽象的原则讲再多,不如亲手拆一棵树。假设要做一个"文章卡片 + 作者信息 + 阅读数 + 收藏按钮"的小列表条目,全写在一个大组件里会长成一大坨 props 和一大段 return。拆法很简单——按"一个方块一块职责"往下分:
function AuthorBlock({ name, avatar }) { return <div><img src={avatar} alt={name} /><span>{name}</span></div>; } function Stats({ views, likes }) { return <p>{views} 阅读 · {likes} 点赞</p>; } function ArticleCard({ post, onToggleLike }) { return ( <article> <h3>{post.title}</h3> <AuthorBlock name={post.author} avatar={post.avatar} /> <Stats views={post.views} likes={post.likes} /> <button onClick={() => onToggleLike(post.id)}>收藏</button> </article> ); }
拆完立刻能看出三好处:AuthorBlock、Stats 这类小件通用性强,别的列表直接复用;ArticleCard 只管把零件拼起来,职责单一;任何一个零件要改,"去哪改"一目了然。这就是"嵌套"在工程上的价值——它不是层层叠 CSS 样式,而是把复杂界面递归地切成可独立测试、可复用的单元。
拆的时候有一条边界别越线:别为了一眼快感把还不需要复用的代码也硬拆成零件。一棵"只出现一次、逻辑也不长"的树,硬拆反而是负担——你为不存在的复用买了单。拆与不拆的判断尺度和前面审组件一致:有没有第二个地方真的要用它、拆出来是不是更清楚。这两问回答都是"是",才放心下刀。
组件能定义和嵌套了,接下来最关键的是它们之间怎么通信息。下一节进入组件通信——父子、兄弟、跨层各有各的路。