组件就是一个返回界面的函数A component is a function that returns what you see on screen
从这个项目最短的两个文件开始:App.tsx 只有 5 行。Start with the two shortest files in this project: App.tsx is only 5 lines.
这一页有什么On this page7
- 说清「组件」在 React 里到底是什么Explain what a component actually is in React
- 看懂 JSX 里的标签、花括号、classNameRead the tags, the curly braces, and className in JSX
- 知道组件名必须大写开头,以及为什么Know that a component name must start with a capital letter, and why
- 能画出这个项目的组件树Draw the component tree of this project
Q1 的四个组件是给好的骨架,你要在里面填逻辑。填之前必须先看懂「谁渲染谁、数据从哪来」,否则会把代码写在错误的组件里。In Q1 the four components are already written for you, and you add the logic inside them. Before you add anything, you have to see which component renders which, and where the data comes from. Otherwise you put the code in the wrong component.
react-notes-app/src/App.tsx整个应用的根组件,只有 5 行The root component of the whole app, five lines long
react-notes-app/src/App.tsxreact-notes-app/src/components/NoteItem/index.tsx最简单的展示型组件The simplest presentational component
react-notes-app/src/components/NoteItem/index.tsx一个组件 = 一个返回 JSX 的函数A component is a function that returns JSX
没有别的了。它不是类、不是模板、不是配置。That is all it is. Not a class, not a template, not a config file.
看这个项目里最短的文件。App 是一个普通的 JavaScript 函数, 它没有参数,return 一个看起来像 HTML 的东西:
那个 <NoteManager /> 不是 HTML 标签 —— HTML 里没有这个元素。它是在说「把 NoteManager 这个组件渲染在这里」。 这种「在 JavaScript 里直接写标签」的语法叫JSX,它会被构建工具(这个项目里是 Vite) 翻译成普通的函数调用。
为什么组件名必须大写开头?因为 JSX 靠首字母区分两件事:小写开头(<div>、<input>)当成真实 HTML 标签; 大写开头(<NoteManager />)当成你的组件。 写成 <noteManager />,React 会去找一个叫 notemanager 的 HTML 标签,然后什么都不显示 —— 而且不报错。
Look at the shortest file in this project. App is a plain JavaScript function. It takes no arguments and returns something that looks like HTML:
That <NoteManager /> is not an HTML tag — there is no such element in HTML. It says “render the NoteManager component right here”. Writing tags directly inside JavaScript like this is called JSX, and the build tool (Vite, in this project) turns it into ordinary function calls.
Why must a component name start with a capital?Because JSX tells two things apart by that first letter: lowercase (<div>, <input>) means a real HTML tag; uppercase (<NoteManager />) means your component. Write <noteManager /> and React goes hunting for an HTML tag called notemanager, then renders nothing — and says nothing about it.
react-notes-app/src/App.tsxJSX 的几条硬规则The rules JSX always enforces
看 NoteItem,这是这个项目里最纯粹的展示型组件。 它把这些规则都用到了:
- 只能返回一个根元素。这里返回的是一个
<tr>,里面包着四个<td>。想并列返回两个同级元素, 要用<>...</>包起来。 - 花括号
{}是「切回 JavaScript」的开关。{note.title}的意思是「这里放note.title这个变量的值」。 写成note.title(不带花括号)会原样显示这十个字符。 - 属性名用 camelCase,
class要写className。因为class是 JavaScript 的保留字。同理onclick要写onClick。 - 自闭合标签必须带斜杠。HTML 里
<input>可以不闭合,JSX 里必须写<input />。
Look at NoteItem, the purest display component in this project. It uses every one of these rules:
- One root element only. This one returns a single
<tr>wrapping four<td>. To return two siblings side by side, wrap them in<>...</>. - Braces
{}switch you back into JavaScript.{note.title}means “put the value ofnote.titlehere”. Written asnote.titlewithout braces, that text shows up on the page literally. - Attributes are camelCase, and
classbecomesclassName. Becauseclassis a reserved word in JavaScript. Same reasononclickis writtenonClick. - Self-closing tags need the slash. HTML lets you leave
<input>open; JSX makes you write<input />.
react-notes-app/src/components/NoteItem/index.tsx这个项目的组件树The component tree of this project
四个组件,一条主干。记住这张图,Q1 的三道题就都有落点了。Four components, one main line. Remember this picture and each of the three Q1 tasks has a place to go.
NoteManager 在中间,它同时是 NoteForm 和NoteTable 的父组件。这个位置决定了它是唯一能同时影响表单和表格的地方 —— 所以三道题的代码全都写在它里面。
NoteTable 和 NoteItem 都是纯展示的: 它们不持有任何数据,只负责「把拿到的东西画出来」和 「把用户的点击原样上报给上面」。
NoteManager sits in the middle: it is the parent of both NoteForm and NoteTable. That position makes it the only place that can touch the form and the table at the same time — which is why all three tasks are written inside it.
NoteTable and NoteItem are pure display: they hold no data at all. They draw what they are handed, and pass the user’s clicks straight back up.
React.FC 是什么What React.FC is
这个项目里所有组件都写成const X: React.FC<XProps> = ({...}) => {...}。
React.FC 是 React 提供的一个类型, 全称 Function Component。React.FC<NoteItemProps> 的意思是: 「这是一个函数组件,它的 props 类型是 NoteItemProps」。
它不是必须的 —— 直接写function NoteItem(props: NoteItemProps) {...}完全等价。但这个项目统一用了 React.FC,你写的代码应该跟着项目的风格。 考试不会因为风格扣分,但保持一致会让人觉得你读过代码。
Every component in this project is written as const X: React.FC<XProps> = ({...}) => {...}.
React.FC is a type that React ships, short for Function Component. React.FC<NoteItemProps> says: “this is a function component, and its props are typed NoteItemProps”.
It is not required —function NoteItem(props: NoteItemProps) {...}is exactly equivalent. But this project uses React.FC everywhere, and your code should follow the project. Nobody loses points for style, but matching it shows you read the code.
动手做Get your hands on it
填空只是过渡。真正掌握的标准,是在没有答案的时候从头写出来 —— 所以做完 L2 之后一定要往 L3、L4 走。Filling blanks is a stepping stone. The real bar is writing it from nothing, so once L2 is comfortable, push on to L3 and L4.
下面哪一行会在页面上显示这条笔记的标题内容?
Which line below shows the title of this note on the page?
Q1 的三个任务(Add / Delete / Edit)都要改动笔记列表。 这些逻辑主要写在哪个文件里?
All three tasks in Q1 (Add / Delete / Edit) change the note list. Which file holds most of that logic?
初学者常见的几种写法错误Mistakes beginners actually make
下面每一段都是「能编译、但结果不对」或者「一跑就炸」的真实写法。先自己看出问题在哪,再看解释。Every snippet below either compiles and gives the wrong answer, or blows up on the first run. Spot the problem yourself before reading the explanation.
JSX expressions must have one parent element。 解法是用真正的父元素(这里是 <tr>) 或者空标签 <>...</> 包起来。JSX can return only one root element. This code fails to compile with JSX expressions must have one parent element. Fix it by wrapping the elements in a real parent (here that is<tr>) or in an empty tag<>...</>.换一道题也能用Works on other problems too
考试不会原题重考。真正能带走的是「看到这种信号 → 伸手去拿这个解法」。The exam will not reuse the same question. What you take away is the reflex: see this signal, reach for that solution.
- 组件就是返回 JSX 的普通函数,名字必须大写开头。A component is a plain function that returns JSX, and its name must start with a capital letter.
- 花括号是切回 JavaScript 的开关;class 要写 className。Curly braces switch back to JavaScript; write className, not class.
- JSX 只能返回一个根元素,需要并列时用 <>…</>。JSX can return only one root element. Use <>…</> when you need several elements side by side.
- 这个项目的组件树:App → NoteManager →(NoteForm + NoteTable → NoteItem)。The component tree here: App → NoteManager → (NoteForm + NoteTable → NoteItem).
- NoteManager 是唯一能同时影响表单和表格的地方,三道题都落在它里面。NoteManager is the only place that can affect the form and the table at the same time, so all three tasks land inside it.