尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

全栈项目从 0 到 1 实战(6):前端页面与联调

全栈项目从 0 到 1 实战(6):前端页面与联调 上一篇完成了带授权、分页、幂等和版本控制的任务 API本篇让 React 页面真正消费这份契约。联调的完成标准不是“我的浏览器出现了一条任务”而是刷新、分享链接、慢网、过期会话和并发编辑下仍有确定行为。我们将用状态归属和错误语义组织页面这套判断可直接迁移到 Vue、Svelte 或移动端。一、痛点页面成功一次不等于联调完成任务列表至少有五种状态首次加载、成功有数据、成功为空、请求失败、后台刷新。只写data List /会让空数组与未加载混淆。编辑表单还要面对字段校验、重复提交、令牌刷新和 409 冲突。若每个组件自行fetch、拼 URL、判断状态码错误处理与类型会迅速分叉。先问“谁是这份状态的权威来源”。筛选、排序和页码的权威是 URL因为刷新、后退与分享都要复现输入中但未提交的值属于表单从 API 得到的任务由服务端拥有前端缓存只是带时效的副本模态框开关等短暂交互才属于组件。React Router、TanStack Query、React Hook Form 和 Zod 分别承接这些职责。换库时只要所有权不变页面就不会重新退化成散落的fetch和布尔变量。查询还应有显式状态模型pending表示没有可显示数据success-empty表示请求成功但集合为空success-data表示有数据error表示没有可用结果refreshing表示旧数据仍可读但后台正在更新。把空数组当成“还没加载”会制造永久骨架屏后台刷新时清空列表则会造成视觉闪烁和焦点丢失。二、原理静态类型不能验证网络数据TypeScript 类型在编译后消失后端错误、代理缓存或旧版本都可能返回不符合声明的数据。边界处应做最小运行时校验再转为领域对象。以下独立 Python 程序模拟前端解码器展示“字段存在”之外还要检查枚举、类型和未知输入。fromdataclassesimportdataclassfromtypingimportAnydataclass(frozenTrue)classTask:task_id:strtitle:strstatus:strversion:intdefdecode_task(value:Any)-Task:ifnotisinstance(value,dict):raiseValueError(task must be an object)required{id,title,status,version}missingrequired-value.keys()ifmissing:raiseValueError(missing: ,.join(sorted(missing)))ifnotisinstance(value[id],str)ornotvalue[id]:raiseValueError(id must be a non-empty string)ifnotisinstance(value[title],str)ornotvalue[title].strip():raiseValueError(title must be non-empty)ifvalue[status]notin{todo,doing,done}:raiseValueError(unknown status)ifnotisinstance(value[version],int)orvalue[version]1:raiseValueError(invalid version)returnTask(value[id],value[title].strip(),value[status],value[version])raw{id:t1,title: 完成联调 ,status:doing,version:2}taskdecode_task(raw)print(ftask{task.task_id}title{task.title})try:decode_task({**raw,status:unknown})exceptValueErroraserror:print(frejected{error})运行输出taskt1 title完成联调 rejectedunknown statusOpenAPI 可生成 TypeScript 类型和客户端但生成目录应视为构建产物不手改CI 检查规范变化是否同步。生成类型也不免除关键边界的运行时检查因为实际响应可能来自旧服务、缓存或错误网关。HTTP 客户端集中设置基础路径、JSON 解析、请求 ID、认证刷新和错误映射业务 hook 只接收领域参数。解码失败要被记录为契约错误而不是伪装成“列表为空”。三、实现以用户动作组织数据流任务页从 URL 读取status和cursor并先把非法值规范化。查询键必须包含工作区、项目、筛选、排序和游标漏掉工作区不仅显示错误数据还可能造成跨租户信息闪现。创建成功后可以失效列表并重新获取追求即时反馈时才做乐观更新而且必须有快照、回滚和最终重新校验。状态切换等简单可逆动作适合乐观更新服务端生成 ID、权限和默认字段的复杂创建通常等待真实响应更稳妥。下面程序模拟缓存中的乐观更新、服务器拒绝与回滚。它把快照作为事务补偿思想可直接映射到 TanStack Query 的onMutate/onError/onSettled。fromcopyimportdeepcopy cache{tasks:[{id:t1,status:todo,version:1},{id:t2,status:doing,version:3},]}defoptimistic_status(task_id:str,new_status:str)-list[dict]:ifnew_statusnotin{todo,doing,done}:raiseValueError(invalid status)snapshotdeepcopy(cache[tasks])foundFalsefortaskincache[tasks]:iftask[id]task_id:task[status]new_status foundTrueifnotfound:raiseKeyError(task_id)returnsnapshotdefrollback(snapshot:list[dict])-None:cache[tasks]snapshot snapshotoptimistic_status(t1,done)print(optimisticcache[tasks][0][status])server_response{ok:False,code:version_conflict}ifnotserver_response[ok]:rollback(snapshot)print(errorserver_response[code])print(finalcache[tasks][0][status])print(versionstr(cache[tasks][0][version]))运行输出optimisticdone errorversion_conflict finaltodo version1表单提交开始后禁用重复提交并为一次用户意图复用同一幂等键网络重试若生成新键后端仍可能创建两次。422 的details映射到具体字段无法映射的错误放表单摘要网络失败保留输入并提供重试。409 时不能直接用本地内容覆盖展示服务器最新版、用户草稿和冲突字段让用户决定重新应用。401 只触发一次共享刷新流程并发请求等待同一个刷新 Promise避免刷新令牌轮换被自己的并发请求判成重放。错误提示必须告诉用户下一步。无权限是“联系工作区管理员”冲突是“加载最新版”离线是“保留内容并重试”未知故障则展示请求 ID 便于支持人员定位。不要把后端 message 原样显示前端依据稳定code选择本地化文案后端 message 只作安全的补充。可访问性在组件设计时完成表单标签与输入关联错误用aria-describedby焦点在对话框打开和关闭时正确移动状态不能只靠颜色键盘可完成所有操作。骨架屏应与布局尺寸匹配以减少跳动后台刷新保留旧数据并显示轻量指示不把整个页面重新变成空白。四、踩坑缓存失效比请求本身更难退出登录必须清理用户相关缓存切换工作区也要先改变查询键再渲染数据。不要无限重试 4xxGET 的瞬时网络错误可指数退避并加入抖动写请求只有满足幂等条件才自动重试。开发环境 React Strict Mode 可能让副作用重复执行这是在暴露不纯的 effect 或缺失的清理函数应修复根因。请求取消也要区分用户切换筛选导致的取消不是错误不应弹出失败通知。代理路径、Cookie 域、HTTPS 和 SameSite 在本地与生产不同联调文档应记录拓扑。浏览器 CORS 报错常掩盖后端 500要同时检查网络响应与服务日志。不要在组件里吞异常错误边界负责渲染崩溃查询错误由页面状态处理两者职责不同。五、验证以用户旅程而非组件数量验收验收按用户旅程编排登录进入项目、通过可分享 URL 筛选待办、创建任务、刷新后仍存在、两窗口编辑同一记录出现冲突、离线后恢复、会话过期只刷新一次、无权限按钮不可见且直接调用 API 仍被拒绝。浏览器自动化应观察用户可见结果不绑定组件内部状态契约测试负责字段与错误 code。再用慢速网络和键盘操作检查焦点、骨架尺寸、重复请求、按钮禁用与取消请求。可迁移的联调清单只有四问状态由谁拥有缓存键是否包含全部身份与筛选维度失败后用户能否继续服务端真相回来后怎样收敛。回答清楚后页面组件只是这些决策的呈现层而不是第二套业务后端。前后端主链路现在已经闭环。下一篇处理最容易脱离主链路的附件上传与第三方服务预签名直传、文件校验、webhook 签名、超时重试和事件幂等。参考来源React官方文档TanStack Query官方文档React Router官方文档WAI表单可访问性教程 觉得有用就点个赞 收藏方便回头查阅有疑问直接在评论区留言我看到都会回。 本文属于《全栈项目从 0 到 1 实战》系列持续更新关注不迷路。 文章里的代码都能直接跑。想要可直接 clone 的完整工程 配套部署脚本 / 踩坑清单评论一声或发邮件到cj2664qq.com我免费发你。如果你正好在做类似系统、或有工程化难题想找人做也欢迎邮件聊一句——我按实际情况评估能落地的就接单或出方案。评论和邮件都能直接找到我不用跳别的平台。
返回列表