从零开始学前端 | 第三十三章:第四阶段综合实战:记账板功能规划与页面搭建
本章定位前面七章你已经把 React 第四阶段最重要的基础能力走完了。你已经系统接触过这些内容React 是什么为什么适合现代前端项目。JSX 与组件基础。Props与组件复用。State、事件与受控组件。列表渲染、条件渲染与组件通信。useEffect与数据请求。React 表单、状态整理与项目结构。也就是说到现在为止你已经不只是会写单个小例子而是已经具备了进入一个中小型 React 项目的基础。现在终于到了第四阶段最关键的节点不再只学零散的 React 知识点而是把这些知识点真正拼成一个完整的交互项目。这次综合实战我们选择的主题是记账板它非常适合作为 React 阶段的第一个完整项目因为它天然会把前面学过的很多核心能力串起来组件拆分PropsState表单处理列表渲染条件渲染组件通信useEffect页面结构整理但这篇我们不会一上来就把所有逻辑一次性写满。这一篇的重点是两件事把记账板项目的功能规划想清楚。把页面骨架和组件结构先搭起来。所以你可以把这一章理解成第四阶段综合实战的起步篇先把项目蓝图和页面地基搭好。本章学习目标学完这一章后你应该能做到理解记账板项目为什么适合作为 React 阶段综合实战。知道一个记账板页面通常要包含哪些核心功能。学会从功能、数据、状态、界面四个角度拆解项目。理解这个项目里最核心的数据结构应该长什么样。知道哪些状态适合放在页面层哪些适合下沉到子组件。掌握一个适合初学者的 React TypeScript 小项目目录结构。学会先搭页面骨架、再补交互逻辑的开发顺序。能写出记账板首页的基础组件结构和页面布局。建立“先规划再编码先结构再细节”的项目意识。为下一篇继续实现表单录入、列表渲染与统计逻辑做好准备。一、这次综合实战到底要做什么这次我们要做的不是一个只展示几条静态内容的页面而是一个真正具备表单录入数据列表分类筛选统计展示状态切换这些能力的小型 React 应用。这个记账板至少要支持下面这些核心功能新增一条账单记录区分收入和支出记录分类、金额、日期和备注按“全部 / 收入 / 支出”进行筛选显示总收入、总支出和当前结余在列表中展示所有账单记录当没有记录时显示空状态提示如果后面你还想继续扩展它也非常适合再加编辑记录删除记录本地存储搜索关键词按日期排序你可以先把这个项目理解成一个真正开始具备“表单 列表 筛选 统计”完整闭环的 React 小项目。二、为什么记账板特别适合做 React 阶段综合实战因为它天然会逼着你把前面学过的知识串起来。1. 它一定会用到受控组件因为你需要录入类型分类金额日期备注这些字段都离不开表单状态管理。2. 它一定会用到列表渲染因为账单记录天生就是一组数据。你几乎一定会写到数组数据 - 一组账单卡片或列表项3. 它一定会用到条件渲染例如没有数据时显示空状态有数据时显示列表当前是收入筛选还是支出筛选4. 它一定会用到组件通信因为很自然就会拆成表单组件统计组件筛选组件列表组件这些组件不可能彼此孤立工作。5. 它很适合练项目结构整理因为功能比“计数器”“单输入框”复杂但又没有复杂到让初学者完全失控。这正是一个很好的练习区间。三、完成后页面大概会长什么样你可以先想象一个简洁、清楚、适合练项目结构的记账板页面。它大概会包含这些区域1. 顶部说明区例如页面标题一句当前项目说明当前总记录数2. 统计卡片区例如三张卡片总收入总支出当前结余3. 筛选区例如全部收入支出4. 表单区负责新增或编辑账单记录。至少会有收支类型分类金额日期备注提交按钮5. 列表区负责显示账单明细。每条记录里可能会有类型标签分类名称金额日期备注6. 空状态区当当前筛选下没有数据时页面应该给用户明确反馈而不是“什么都没有”。这一点非常重要。四、先别急着写代码先拆功能模块项目越早拆清楚后面越轻松。这一点在综合实战里尤其重要。你可以先把这个记账板拆成下面几个模块。1. 录入模块负责收集表单值校验输入内容提交新增记录2. 列表渲染模块负责把账单数组渲染成界面显示每条记录的关键信息3. 筛选模块负责切换当前筛选条件根据筛选结果更新列表4. 统计模块负责计算总收入计算总支出计算当前结余5. 提示模块负责空状态提示成功或失败提示当前筛选说明只要你先把模块拆出来后面写 React 代码时就不会那么容易一股脑堆在一起。五、再把这个项目拆成“数据、状态、界面、交互”这一节非常重要。因为一旦你开始写综合项目就不能只盯着“页面长什么样”。你还得学会从多个层面看问题。1. 数据项目最核心的数据就是账单记录数组当前表单值2. 状态项目最核心的状态可能会有当前筛选类型当前是否在编辑模式当前提示信息当前是否正在提交3. 界面项目最核心的界面区域有标题区统计区筛选区表单区列表区4. 交互项目最核心的交互有输入表单点击提交切换筛选更新列表5. 为什么这一步特别关键因为很多初学者写项目时脑子里只有一整页 JSX没有更细的结构层次。而真正让你后面越写越轻松的往往就是你能不能先把项目拆成立体结构而不是只看成一张页面。六、先把记账板最核心的数据模型想清楚这一节非常关键。因为功能可以慢慢补但数据模型一开始就应该尽量想清楚。先看最核心的一条账单记录可以长什么样。interfaceRecordItem{id:number;type:income|expense;category:string;amount:number;date:string;note:string;}1. 这里每个字段分别在表达什么id每条记录的唯一标识type收入还是支出category例如工资、餐饮、交通、学习等amount金额date发生日期note补充说明2. 为什么这个结构很适合作为第一版因为它已经足够支撑表单录入列表渲染分类筛选统计计算但它又没有复杂到让纯小白一下子被数据结构压住。七、表单值和最终记录对象为什么也值得分开看这一点很重要。虽然当前阶段你不一定必须立刻拆两个接口但你最好先有这个意识。例如表单值可以先理解成interfaceRecordFormValue{type:income|expense;category:string;amount:string;date:string;note:string;}1. 为什么这里的amount先是字符串因为输入框里拿到的值默认更接近字符串形态。而最终业务对象里的amount更适合是数字。这就说明表单值和最终记录数据有时候不是完全同一种形态。2. 当前阶段先记住什么就够了你现在先建立一个意识录入阶段的数据和真正进入业务数组的数据不一定完全相同。这个意识会让你后面写表单和校验时更稳。八、这个项目里最值得先想清楚的几个状态这一步也很重要。因为项目一旦进入 React很多混乱其实都来自状态没想清楚。当前阶段你可以先重点考虑这几个。1. 记录列表状态例如recordList它保存当前所有账单记录。2. 表单值状态例如formValue它保存当前输入框里的内容。3. 当前筛选状态例如filterType它决定当前列表显示全部、收入还是支出。4. 表单模式状态例如formMode它可以帮助你在后面区分新增模式编辑模式5. 提示信息状态例如message它用来显示当前操作反馈。6. 当前阶段为什么不建议一开始想太多状态因为初学阶段最容易出现的问题之一就是还没写功能先给自己准备了一大堆不一定用得上的状态。更稳的做法是先抓住真正会影响当前页面的核心状态。九、项目目录和运行方式怎么准备因为这是 React 阶段综合实战所以这一篇我们直接用React TypeScript Vite这是一个非常适合当前阶段的小项目组合。1. 一个适合初学者的目录结构account-board/ ├── src/ │ ├── components/ │ │ ├── RecordForm.tsx │ │ ├── SummaryCards.tsx │ │ ├── FilterTabs.tsx │ │ └── RecordList.tsx │ ├── types/ │ │ └── record.ts │ ├── App.tsx │ ├── main.tsx │ └── index.css ├── package.json └── tsconfig.json2. 为什么这一版目录很适合当前阶段因为它已经有了最基础的分层components/放组件types/放类型App.tsx负责组合页面index.css负责全局样式但它又没有复杂到让你一开始就被目录结构压住。3. 如果你要手动创建项目可以先执行pnpmcreate vite account-board--templatereact-tscdaccount-boardpnpminstallpnpmdev当前阶段你不必把 Vite 配置研究得很深。先把项目跑起来再进入页面组织会更自然。十、先把页面组件怎么拆想清楚这一篇的核心不是先写复杂逻辑而是先把页面骨架搭清楚。当前阶段你可以先把页面拆成这样App ├── Header ├── SummaryCards ├── FilterTabs ├── RecordForm └── RecordList1.Header负责什么负责页面标题项目说明2.SummaryCards负责什么负责展示总收入总支出当前结余3.FilterTabs负责什么负责切换全部收入支出4.RecordForm负责什么负责表单输入提交按钮基础提示5.RecordList负责什么负责记录列表渲染空状态展示这一步非常关键。因为它决定了你后面代码会不会一开始就全堆到App里。十一、为什么这一篇先搭页面骨架不急着把逻辑写满很多初学者做综合实战时最容易犯的错误就是一上来就同时写页面、状态、校验、筛选、统计、请求。这样通常会很快乱掉。当前阶段更稳的顺序是先把项目目标想清楚先把数据模型想清楚先把组件骨架搭起来再逐步填状态和交互这种顺序的好处是你始终知道自己现在在补哪一层而不是所有层一起打架。十二、先写App.tsx的页面骨架下面先看一个非常适合作为起点的App.tsx结构。function App() { return ( main classNameapp-shell header classNamehero p classNameeyebrow第四阶段综合实战/p h1记账板/h1 p classNamehero-desc用 React 搭建一个能记录收入和支出的交互面板。/p /header section classNamedashboard-grid section classNamepanel统计区/section section classNamepanel筛选区/section section classNamepanel表单区/section section classNamepanel列表区/section /section /main ); }1. 这段代码当前阶段最重要的价值是什么不是它功能多而是它先把页面大区域视觉层级功能区块这些地基搭起来了。2. 为什么这比一开始就写复杂逻辑更稳因为只要结构先清楚后面你每加一个功能就更容易知道它该落在哪个区域。十三、再把骨架换成组件组合方式当你已经知道页面有哪些区域后就可以开始真正拆成组件。例如import { FilterTabs } from ./components/FilterTabs; import { RecordForm } from ./components/RecordForm; import { RecordList } from ./components/RecordList; import { SummaryCards } from ./components/SummaryCards; function App() { return ( main classNameapp-shell header classNamehero p classNameeyebrow第四阶段综合实战/p h1记账板/h1 /header SummaryCards / FilterTabs / RecordForm / RecordList / /main ); }1. 为什么这里先不急着传很多props因为这一篇的重点是先把组件的职责边界搭出来。后面当我们真正实现筛选、提交和列表更新时再把状态和回调接进来会更稳。2. 这一节最想帮你建立什么感觉就是一个页面不是先天就是一整页而是可以被拆成一组有职责的组件。十四、四个核心子组件的第一页写法应该长什么样当前阶段你不需要一上来就把子组件写满。先写“占位版”其实非常有价值。例如export function SummaryCards() { return section classNamepanel统计卡片区域/section; }export function FilterTabs() { return section classNamepanel筛选标签区域/section; }export function RecordForm() { return section classNamepanel账单录入表单区域/section; }export function RecordList() { return section classNamepanel账单列表区域/section; }1. 为什么“占位组件”也值得先写因为它会帮你确认页面拆分是否合理目录组织是否顺手组件边界是否清楚2. 当前阶段最怕什么最怕的是还没想清组件边界就直接往一个组件里猛加逻辑。这会让后面越来越难拆。十五、再给页面定一个适合初学者的视觉目标这一篇虽然不是设计课但页面结构和视觉层级关系非常大。你可以先给这个记账板设一个很实用的视觉目标页面结构清楚功能分区明显重点信息先被看到当前阶段最推荐的版式思路是顶部一块说明区下方先放统计卡片再放筛选和表单最后是记录列表这样用户路径会非常自然先看项目是什么再看当前结果再进行筛选或录入最后看明细。十六、一个适合作为第一版的样式结构思路你现在不必追求特别复杂的视觉设计。第一版只要做到这些就已经很好1. 页面外层有最大宽度控制让内容不要铺得太散。2. 每个功能区用panel包起来这会让统计区表单区列表区一眼就分得更清楚。3. 统计区适合用卡片网格这样“总收入 / 总支出 / 结余”三块信息的视觉优先级会很清楚。4. 表单和列表要有明显层级区分因为它们的功能完全不同。这一节最重要的不是样式细节而是建立页面布局也在服务功能理解。十七、如果现在只做页面搭建第一版应该达到什么程度这一点很重要。因为很多初学者会不自觉给自己加压是不是这一篇就要把全部交互做完不是。既然这一篇是“功能规划与页面搭建”那么第一版做到这些就已经很好项目目标明确核心数据模型明确组件拆分明确页面骨架能完整显示每个区域的职责已经清楚只要这些地基打稳后面补表单录入列表新增筛选更新统计计算都会顺很多。十八、一个适合本项目的第一版开发顺序这一节很实用。因为综合实战最怕不是难而是顺序乱。你可以先按这个顺序推进创建 React TypeScript 项目整理目录结构定义核心类型搭页面骨架拆出占位组件再逐步补表单、列表、筛选和统计逻辑这条顺序背后的核心思想是先稳住结构再往里填功能。十九、这一篇里最容易踩的几个坑这一节建议你认真看。因为综合实战刚开始时很多问题不是技术本身而是节奏和组织方式不对。1. 坑一还没规划功能就直接开始写 JSX这样后面很容易越写越像“边搭边猜”。2. 坑二所有区域都先堆进App.tsx这在最早起步时可以临时接受但如果不尽快拆分后面会越来越难整理。3. 坑三数据结构没想清楚就先写交互这会直接导致状态越写越乱表单值和业务值混在一起后面改起来特别痛苦4. 坑四目录一上来拆得太细结构化不是拆得越多越好。当前阶段最稳的是先做最小但清楚的分层。5. 坑五第一篇就想把所有功能做完综合实战不是一口吞下去的。它更适合先搭蓝图再一层层补完整。二十、本章实践练习这一章的练习重点不是把所有交互一次做完而是把项目地基搭稳。1. 练习 1手写记账板功能清单请你先不用写代码先把你认为记账板第一版必须有的功能写出来。至少写出新增记录列表展示类型筛选统计信息这个练习的重点是从“看页面”切换到“先做功能规划”。2. 练习 2画出组件树请你根据这一章内容画出你自己的记账板组件树。至少包含AppSummaryCardsFilterTabsRecordFormRecordList这个练习会帮助你真正建立页面不是一整页而是一棵组件树。3. 练习 3创建项目并写出页面骨架请你用 React TypeScript 项目完成App.tsx基础骨架四个占位组件页面基础区域结构这个练习的重点是先把组件边界和页面结构搭起来。4. 练习 4补出核心类型定义请你把这一章提到的RecordItemRecordFormValue写进独立类型文件里。这个练习会帮助你把项目规划和数据模型真正连接起来。二十一、学习重点提示这一章请你重点记住下面这些话综合实战刚开始时最重要的不是立刻把所有功能做完而是先把目标、结构和顺序想清楚。记账板特别适合用来串联 React 阶段的表单、列表、筛选、统计和组件通信能力。功能规划时可以先从功能、数据、状态、界面四个角度拆解项目。数据模型越早想清楚后面的表单、状态和列表逻辑就越稳。页面骨架先搭起来比一开始就猛写复杂交互更稳。组件拆分应该围绕职责而不是围绕代码行数。目录整理的目标是清楚不是复杂。第一版项目做到“能清楚地显示页面结构”就已经非常有价值。先清楚再细化先结构再交互。如果你只记一句话请记住综合实战的第一步真正拉开差距的往往不是谁代码写得快而是谁先把功能、数据和页面结构想清楚。二十二、本章小结这一章我们正式开启了第四阶段综合实战。你已经理解了记账板为什么适合作为 React 阶段的综合项目这个项目的第一版应该包含哪些核心功能如何从功能、数据、状态、界面四个角度拆解项目账单记录和表单值最基础的数据模型应该怎么想页面组件和项目目录第一版应该怎么搭为什么先搭页面骨架、再补逻辑是一个更稳的开发顺序更重要的是你开始建立一种非常关键的项目意识做项目不是从“先把代码敲出来”开始而是从“先把项目结构理顺”开始。这一步非常关键。因为从这里开始你已经不只是在学 React 知识点而是在开始真正进入React 综合项目的规划与落地阶段。二十三、课后思考题请你认真思考下面这些问题为什么说记账板天然适合作为 React 阶段综合实战为什么综合实战一开始先做功能规划比马上写大量 JSX 更重要记账板项目里哪些内容更适合作为数据哪些更适合作为状态为什么账单记录和表单值有时值得分开看为什么页面骨架和组件边界应该先于复杂交互一个适合初学者的小项目目录最重要的价值是什么为什么第一版项目不应该一口气把所有功能都做完建议你把这些问题用自己的话写下来。只要你能把这些问题讲清楚说明你已经真正开始进入 React 综合实战的主线了。二十四、下一篇预告下一篇我们会继续推进第四阶段综合实战进入第四阶段综合实战记账板表单录入、记录新增与列表初步渲染到那时你会开始真正把这一篇搭好的项目骨架填起来表单状态怎么组织提交新增记录时发生了什么列表怎样根据状态渲染出来空状态什么时候显示也就是说下一篇开始我们会从“项目规划与页面搭建”继续走到记账板第一版核心交互的真正实现。