职位收藏管理该怎么做

拿"职位收藏管理"来说,它看着是个列表页,真正要想清楚的是三件事:数据怎么存、状态放在哪、交互怎么不出错。 一、先把"收藏"这件事的关系定清楚 一个用户能收藏多个职位,一个职位也能被很多人收藏,所以是多对多,不能只在 users 表上加个字段。 三张表大概这样: jobs(id title company_id salary_min salary_max city published_at) favorites(id user_id job_id note created_at unique(user_id job_id)) users(id,...) 关键是 favorites 里加 unique(user_id job_id),从数据库层防重复收藏,别只靠前端按钮置灰。备注 note 挂在收藏关系上,不挂在 jobs 上——因为同一个人对同一个职位只有一条备注,换个人就不一样。 二、接口按"资源"设计,别做成一个万能接口 GET /api/favorites?keyword=&city=&sort=&page= 取收藏列表 POST /api/jobs/:jobId/favorite 收藏 DELETE /api/jobs/:jobId/favorite 取消收藏 PATCH /api/favorites/:id 改备注 列表接口返回的时候直接把 job 信息带出来(join 一下),不要让前端拿到一堆 job_id 再挨个请求,那样十个收藏就是十次请求。 三、前端:状态归属是重点 组件树大概是: FavoritesPage FilterBar(搜索框、城市筛选、排序) FavoriteList FavoriteCard(职位名、公司、薪资、地点、备注、取消收藏按钮) NoteDialog(编辑备注弹窗) 状态这样分: 搜索词、城市、排序条件放 FavoritesPage,因为它同时影响列表和顶部的结果数量显示。 列表数据不要用 useState 手动存,交给请求库(React Query / SWR 之类)按 key 缓存,搜索条件变了 key 变了自动重新请求。 编辑备注的草稿放 NoteDialog 内部,只有保存成功才回写列表。这是最常见的坑:输入一个字就改列表里的正式数据,用户点"取消"时数据已经被改脏了。 还有一条:别用 useEffect 去同步"搜索后的列表"。搜索结果是从原始数据 + 搜索词算出来的,直接算就行,存一份反而容易和源数据不一致。 四、三个真实会踩的问题 1. 连续搜索的竞态。用户快速改了三次搜索词,第一个请求最后才回来,就会把正确结果覆盖掉。做法是给每次请求带一个递增 id 或者用 AbortController,返回时比对一下是不是最新那次。 2. 收藏按钮的反馈。点一下要等接口回来才变色,体验很卡。可以乐观更新:先变蓝,接口失败再变回去并提示。但删除/取消收藏这种不可逆操作,建议加个撤销提示,比弹窗二次确认更顺手。 3. 刷新后数据还在。这句话的潜台词是数据存在服务端,不是存在 localStorage。前端缓存只是加速,真源在数据库。 五、如果只是练手,先砍到最小闭环 别一上来就把分页、虚拟滚动、多条件组合筛选都做了。先做通一条线:能收藏、能在收藏页看到、能取消、能写备注并保存成功、刷新后还在。跑通之后再往里加筛选和排序,每加一个需求就回头看组件和状态结构要不要调整——这个过程本身比页面本身更值钱。 如果你问的是产品交互层面(比如收藏夹怎么分类、要不要支持分组),那可以再说,思路不太一样。