ICE.js 状态管理深度解析:从入门到精通
前言
在现代前端开发中,状态管理是构建复杂应用的关键环节。ICE.js 框架基于 icestore 提供了完善的状态管理解决方案,帮助开发者优雅地处理应用中的各种状态逻辑。本文将全面介绍 ICE.js 中的状态管理机制,包括全局状态和页面级状态的管理方式,以及各种进阶用法。
状态管理基础概念
在 ICE.js 中,状态管理主要围绕以下几个核心概念:
- Model(模型):定义状态的数据结构和操作
- Store(存储):管理多个 Model 的容器
- Reducer:处理同步状态变更的纯函数
- Effect:处理异步操作和副作用的函数
全局状态管理
配置启用
首先需要在项目中安装并配置状态管理插件:
npm install @ice/plugin-store -D
然后在项目配置文件中添加插件:
// ice.config.mts
import { defineConfig } from '@ice/app';
import store from '@ice/plugin-store';
export default defineConfig(() => ({
plugins: [store()],
}));
定义 Model
全局 Model 应定义在 src/models
目录下。以下是一个用户信息 Model 的示例:
// src/models/user.ts
import { createModel } from 'ice';
interface User {
name: string;
id: string;
}
export default createModel({
state: {
name: '',
id: '',
} as User,
reducers: {
update(state, payload) {
return { ...state, ...payload };
},
},
effects: (dispatch) => ({
async getUserInfo() {
const user = await fetchUserInfo(); // 模拟异步请求
this.update(user);
},
}),
});
初始化 Store
在 src/store.ts
中初始化全局 Store:
// src/store.ts
import { createStore } from 'ice';
import user from './models/user';
export default createStore({ user });
组件中使用
在组件中使用全局状态非常简单:
import store from '@/store';
function UserProfile() {
const [userState, userDispatchers] = store.useModel('user');
useEffect(() => {
userDispatchers.getUserInfo();
}, []);
return (
<div>
<p>用户ID: {userState.id}</p>
<p>用户名: {userState.name}</p>
</div>
);
}
页面级状态管理
页面级状态适用于仅在特定页面内共享的数据,其定义方式与全局状态类似,但作用域仅限于当前页面。
定义 Model
页面级 Model 应定义在页面目录下的 models
子目录中:
src/pages/home/
├── models/
│ └── info.ts
├── store.ts
└── index.tsx
// src/pages/home/models/info.ts
import { createModel } from 'ice';
export default createModel({
state: {
title: '默认标题',
},
reducers: {
updateTitle(state, payload) {
return { ...state, title: payload };
},
},
});
初始化 Store
在页面目录下创建 store.ts
:
// src/pages/home/store.ts
import { createStore } from 'ice';
import info from './models/info';
export default createStore({ info });
组件中使用
// src/pages/home/index.tsx
import homeStore from './store';
function HomePage() {
const [infoState, infoDispatchers] = homeStore.useModel('info');
return (
<div>
<h1>{infoState.title}</h1>
<button onClick={() => infoDispatchers.updateTitle('新标题')}>
修改标题
</button>
</div>
);
}
进阶用法
状态初始化
可以在应用启动时设置初始状态:
// src/app.ts
import { defineStoreConfig } from '@ice/plugin-store/types';
export const storeConfig = defineStoreConfig(() => ({
initialStates: {
user: { name: '初始用户', id: '001' },
counter: { count: 10 },
},
}));
Model 间通信
Model 之间可以通过 dispatch 进行通信:
// src/models/task.ts
export default createModel({
effects: (dispatch) => ({
async addTask(task) {
await saveTask(task); // 保存任务
await dispatch.user.refresh(); // 触发用户信息刷新
},
}),
});
不可变状态优化
使用 immer 简化状态更新:
export default createModel({
state: { list: [] },
reducers: {
addItem(state, item) {
state.list.push(item); // 直接修改,immer 会自动处理不可变性
},
},
});
加载状态和错误处理
获取异步操作的加载状态和错误信息:
function TaskList() {
const [state, dispatchers] = store.useModel('task');
const effectsState = store.useModelEffectsState('task');
if (effectsState.fetchTasks.isLoading) {
return <div>加载中...</div>;
}
if (effectsState.fetchTasks.error) {
return <div>加载失败: {effectsState.fetchTasks.error.message}</div>;
}
return <div>{state.tasks.map(renderTask)}</div>;
}
页面状态重置
配置页面切换时自动重置状态:
// ice.config.mts
export default defineConfig(() => ({
plugins: [store({ resetPageState: true })],
}));
Class 组件支持
通过高阶组件在 Class 组件中使用状态:
import store from '@/store';
@store.withModel('todos')
class TodoList extends React.Component {
render() {
const { todos } = this.props;
const [state, dispatchers] = todos;
// ...
}
}
最佳实践
- 合理划分状态:全局状态用于跨组件共享数据,页面状态用于页面内部共享
- 保持 Model 精简:每个 Model 应该只关注单一领域的状态
- 副作用分离:将异步操作放在 effects 中,保持 reducers 的纯净性
- 合理使用 immer:简化复杂对象的更新逻辑
- 错误处理:充分利用 effectsState 提供的错误信息
总结
ICE.js 的状态管理方案提供了从简单到复杂的全方位支持,无论是小型应用还是大型项目,都能找到合适的实现方式。通过本文的介绍,相信你已经掌握了 ICE.js 状态管理的核心概念和实用技巧,可以在实际项目中灵活运用这些知识来构建更健壮的前端应用。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考