这篇文章不聊概念,直接聊一个常见页面:列表页(搜索、分页、加载)。
我之前的写法是很多人熟悉的模式:
- 页面里放多个
useState useEffect里拉数据- 搜索、分页、重置交织在一起
- loading 再单独维护一套
结果是:需求稍一变化,页面就开始变“脆”。
重构目标
我只做一件事:把“业务动作”从页面拿出来,收进模型。
模型层
class ListModel {
items: { id: number; name: string }[] = [];
keyword = "";
page = 1;
pageSize = 10;
total = 0;
changeKeyword(v: string) {
this.keyword = v;
this.page = 1;
}
changePage(p: number) {
this.page = p;
}
@loader.load(true)
async load() {
// 调接口,更新 items/total
}
}
页面层
function ListPage() {
const model = useModel(ListModel, []);
const { isLoading } = useLoader();
useEffect(() => {
model.load();
}, [model.page, model.keyword]);
return (
<>
<input value={model.keyword} onChange={e => model.changeKeyword(e.target.value)} />
<button onClick={() => model.load()} disabled={isLoading(model.load)}>
刷新
</button>
{/* 表格和分页渲染 */}
</>
);
}
重构后最明显的变化
- 页面变“薄”了:只剩渲染和事件绑定
- 业务规则集中:翻页、筛选、重置逻辑都在模型里
- loading 统一:不再手写多个
isLoadingXxx - 测试更直接:模型可脱离 React 单测
这类重构什么时候最值
- 需求还在持续变化
- 页面逻辑已经不止“展示数据”
- 多人协作导致同一页反复改坏
如果只是一次性小页面,没必要上复杂方案。
但只要页面会长期演进,模型化几乎都会回本。
给正在重构的你一个建议
不要“全页一次性重写”,而是先抽三个动作:
changeKeywordchangePageload
先把这三个放进模型,页面复杂度会立刻下降一个台阶。
仓库地址:
GitHub: github.com/ZYF93/easy-…
npm: www.npmjs.com/package/@e7…
如果你愿意,我下一篇可以按“用户中心页”再给一个更复杂的拆分模板(登录态、权限、资料加载、全局通知一起接入)。