5.1 组件定义、注册与嵌套


5.1 组件定义、注册与嵌套

本节摘要:组件如何被定义、注册进应用、再嵌套成一棵树,是组织代码的第一课。React 组件即函数、Vue 组件即单文件组件,两者的注册与嵌套套路虽有差别,但都指向"树越清晰越易维护"。本节把这两套流程对齐讲清。

本节阅读目标
阅读完本节,你应当能够:

  1. 区分组件定义、注册、使用三个环节。
  2. 在 React 与 Vue 里各完成一次组件的注册与嵌套。
  3. 说出"父组件怎么被拆、子组件怎么被复用"的组织原则。

一、三个环节别混淆

把一个组件送上舞台,要过三个环节:

  • 定义:把结构、逻辑、样式写成这个组件自己的样子。
  • 注册:让父级知道这个名字可被使用(局部注册最常用)。
  • 使用:在模板/JSX 里写标签渲染出来。

新手常常把"定义"当成"注册",于是引入没生效、标签找不到,问题多半出在漏了注册这一步。

二、React 的定义与嵌套

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 的定义与注册

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 的"引入即登记"让大部分场景不再需要手动注册列表,省掉了一类常见错误。

四、图:定义-注册-使用的落地对比

图:React 与 Vue 组件登场流程对照

图:React 与 Vue 组件登场流程对照

五、组织原则与常见坑

  • 单一职责:一个组件只负责一件明确的事,过长就拆(回到 2.1 的评审三问)。
  • 命名一致性:文件名与组件名对得上,Vue 更依赖文件定位。
  • 别过度嵌套:层层透传会让深入调试变难,必要时用插槽或共享层(5.2、5.3)。

三个高频坑:忘注册导致标签没渲染、导入路径写错导致的编译错、命名不一致让人找不到组件。都排查一遍能省很多调试时间。

五·一、注册粒度:局部够用,全局要克制

注册有粒度之分:局部注册把组件挂在某个父组件名下,只在那一棵里可用;全局注册让组件处处可用,不用每个父组件都 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 样式,而是把复杂界面递归地切成可独立测试、可复用的单元。

拆的时候有一条边界别越线:别为了一眼快感把还不需要复用的代码也硬拆成零件。一棵"只出现一次、逻辑也不长"的树,硬拆反而是负担——你为不存在的复用买了单。拆与不拆的判断尺度和前面审组件一致:有没有第二个地方真的要用它、拆出来是不是更清楚。这两问回答都是"是",才放心下刀。

本节要点回顾

  • 三环节:定义、注册、使用,顺序别乱。
  • React/Vue 同构:函数即组件 / import 即登记,流程相通。
  • 组织两则:单一职责 + 命名一致。
  • 三个高频坑:忘注册、错路径、命名不一致。

组件能定义和嵌套了,接下来最关键的是它们之间怎么通信息。下一节进入组件通信——父子、兄弟、跨层各有各的路。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U