最近React项目开发中, 想把数据、逻辑、视图分离,以提升项目的可维护性、可扩展性和可测性,记录下我用的分离方式
先看个代码示例吧:
数据请求(useData.js)逻辑封装也可以用useHook
如果业务开发中有许多兄弟或者子(孙)组件,可以利用useContext/Provider,这样每个组件都可以用useContext拿到useData.js的数据
js
// hooks/useData.js
import { useState, useEffect } from 'react';
export function useData(userId) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`/api/user/${userId}`)
.then(res => res.json())
.then(json => setData(json))
.finally(() => setLoading(false));
}, [userId]);
return { data, loading };
}
视图组件(Box.js)
js
// components/Box.js
export function Box({ user, loading }) {
if (loading) return <div>加载中...</div>;
if (!user) return <div>未找到用户</div>;
return (
<div>
<h2>{user.name}</h2>
<p>邮箱:{user.email}</p>
</div>
);
}
容器组件(UserContainer.js)
js
// containers/UserContainer.js
import { useUserData } from '../hooks/useUserData';
import { UserView } from '../components/UserView';
export function UserContainer({ userId }) {
const { data, loading } = useUserData(userId);
return <UserView user={data} loading={loading} />;
}
总结:
- 数据:用 hooks/service 统一管理和请求。
- 逻辑:可以用 hooks/service 封装,容器组件只调用 或者 直接写在容器组件。
- 视图:纯展示组件,无业务逻辑和数据请求。
这样,可以有效实现"数据、逻辑、视图"三者的分离,使代码更清晰易维护
解释
数据层(Data)
- 状态管理 :使用 React 的
useState
、useReducer
,或外部库(如 Redux、MobX、Recoil、Zustand 等)管理数据。 - 数据请求 :将 API 请求封装在单独的模块或 hooks(如
useFetchUser
),避免在组件内直接请求和处理数据。 - 数据抽象 :通过自定义 hooks(如
useUserData
)将数据获取和处理逻辑与 UI 解耦。
逻辑层(Logic)
- 自定义 Hooks :把业务逻辑、状态操作封装到 hooks(如
useLogin
、useForm
),组件只关心如何展示。 - 服务层:将复杂业务逻辑(如表单验证、流程控制)独立成 service 文件或 hooks。
- 事件处理:事件处理函数尽量独立,不直接写在 JSX 内联。
视图层(View)
-
纯展示组件:只负责渲染 UI,根据 props 显示内容,无内部状态和副作用。
-
容器组件:负责连接数据和逻辑,将数据和事件通过 props 传递给展示组件。