Modern.js 中的 Model 状态管理机制详解
2025-07-08 06:50:25作者:魏献源Searcher
Modern.js 是一个现代化的前端开发框架,它内置了强大的状态管理解决方案 Reduck。本文将深入讲解 Reduck 中的核心概念 - Model,帮助开发者更好地理解和使用这一状态管理机制。
什么是 Model
Model 是 Reduck 中用于管理应用状态的核心单元,它提供了一种组织化的方式来定义和管理应用的状态、计算属性、操作和副作用。每个 Model 都包含以下几个关键部分:
- state - 存储数据状态
- actions - 定义修改状态的方法
- computed - 定义衍生状态(类似 Vue 的计算属性)
- effects - 处理异步操作和副作用
创建 Model 的基本方法
创建 Model 非常简单,只需要调用 model()
函数并传入一个唯一标识符:
const myModel = model('myModel');
这创建了一个 Model 的骨架,接下来我们需要使用 define
方法来定义其具体内容。
定义 Model 的两种方式
1. 对象形式定义
这是最简单直接的 Model 定义方式:
const counterModel = model('counter').define({
state: 0, // 初始状态
actions: {
increment: (state) => state + 1,
decrement: (state) => state - 1,
setValue: (state, value) => value
},
computed: {
doubled: state => state * 2
},
effects: {
async incrementAsync() {
await new Promise(resolve => setTimeout(resolve, 1000));
this.increment(); // 调用 action
}
}
});
2. 函数形式定义
函数形式提供了更强大的灵活性,可以访问上下文和工具函数:
const userModel = model('user').define((context, { use }) => {
return {
state: null,
actions: {
setUser: (state, user) => user
},
effects: {
async fetchUser(userId) {
const response = await fetch(`/api/users/${userId}`);
const user = await response.json();
this.setUser(user); // 调用 action 更新状态
}
}
};
});
Model 的核心组成部分详解
1. State
State 是 Model 中存储数据的地方,建议使用可序列化的数据结构:
state: {
loading: false,
data: null,
error: null
}
2. Actions
Actions 是修改状态的纯函数,Reduck 内部集成了 immer,可以直接修改状态:
actions: {
// 直接修改 state(immer 会处理为不可变更新)
addTodo: (state, todo) => {
state.todos.push(todo);
},
// 或者返回新状态
removeTodo: (state, id) => {
return state.todos.filter(todo => todo.id !== id);
}
}
3. Computed
Computed 属性允许你定义基于 state 的派生数据:
computed: {
// 简单计算属性
todoCount: state => state.todos.length,
// 依赖其他 Model 的计算属性
completedTodos: [
todoModel,
(state, todoState) => state.todos.filter(todo => todoState.completedIds.includes(todo.id))
]
}
4. Effects
Effects 用于处理异步操作和副作用:
effects: {
async loadData() {
try {
this.setState({ loading: true }); // 调用 action
const data = await api.fetchData();
this.setData(data); // 调用 action
} catch (error) {
this.setError(error); // 调用 action
} finally {
this.setState({ loading: false }); // 调用 action
}
}
}
Model 之间的交互
Reduck 提供了优雅的方式让不同 Model 之间进行交互:
const cartModel = model('cart').define((_, { use }) => {
const [userState] = use(userModel); // 使用其他 Model 的状态
return {
state: {
items: [],
userId: userState.id
},
effects: {
async checkout() {
const [cartState] = use(cartModel);
const [userState] = use(userModel);
await api.checkout({
userId: userState.id,
items: cartState.items
});
}
}
};
});
最佳实践
- 单一职责:每个 Model 应该只关注一个特定的功能领域
- 合理拆分:避免创建过于庞大的 Model,必要时拆分为多个小 Model
- 命名规范:为 Model 和它的成员使用清晰的命名
- 类型安全:在 TypeScript 项目中,为 Model 定义完整的类型
- 副作用管理:将异步操作和副作用限制在 effects 中
总结
Modern.js 中的 Reduck 状态管理通过 Model 机制提供了一种结构清晰、易于维护的状态管理方案。通过本文的介绍,你应该已经掌握了如何创建和定义 Model,以及如何利用其各种特性来构建复杂应用的状态管理。Model 的设计既保留了 Redux 的可预测性,又通过 computed 属性和优雅的 Model 间交互机制提供了更高的开发效率。