js-概念什么是领域模型
领域模型是对业务领域内概念、属性、行为和规则的抽象,它存在于 UI 视图层和底层数据(API/数据库)之间。
1. 核心定义 (High-Level Concept)
“领域模型(Domain Model)是解决业务问题的一组抽象概念。在前端开发中,它指的是不依赖于具体 UI 框架(如 React/Vue)的数据结构和业务逻辑层。”
它不是后端返回的 JSON 数据(那是 DTO),也不是 UI 的状态(View Model),而是业务本身的核心逻辑。
2. 前端为什么需要领域模型? (The “Why”)
- 逻辑复用与解耦 (Decoupling):
- UI 组件应该只负责渲染。如果把“计算购物车总价”、“验证用户权限”等逻辑写在组件里,一旦 UI 改版或更换框架,这些逻辑很难复用。
- 领域模型将这些逻辑封装在类(Class)或纯函数中,与 UI 彻底分离。
- 应对接口变更 (Adapter Pattern):
- 后端 API 经常变(字段名从
user_name变成username)。如果没有领域模型,你需要去修改几十个组件文件。 - 如果有领域模型,你只需要在数据转换层(Adapter/ACL)修改一次映射关系即可。
- 后端 API 经常变(字段名从
- 可测试性 (Testability):
- 测试 UI 组件(Cypress/React Testing Library)通常很慢且脆弱。
- 测试领域模型(纯 JS/TS 逻辑)非常快,可以直接编写单元测试验证业务规则。
3. 具体包含什么? (The Components)
在前端上下文中,领域模型通常包含以下几个部分(建议结合 TypeScript 回答):
- 实体 (Entities): 具有唯一标识(ID)的对象。
- 例子:
User,Product,Order。
- 例子:
- 值对象 (Value Objects): 没有 ID,由属性描述的对象,通常是不可变的。
- 例子:
Address(包含省市区),Price(包含数值和货币单位),DateRange。
- 例子:
- 领域服务 (Domain Services): 处理涉及多个实体的复杂业务逻辑。
- 例子:
CartService.checkout(cart, user)。
- 例子:
4. 代码举例 (Show Me The Code)
用一个对比例子最能说明问题。假设我们要展示一个用户的全名。
❌ 做法 A:贫血模型(逻辑散落在组件中)
后端返回 JSON,组件直接使用,逻辑写在 render 里。
1
2
3
4
5
6
7
8
// 组件内部
const UserProfile = ({ apiData }) => {
// 业务逻辑混入 UI
const fullName = `${apiData.first_name} ${apiData.last_name.toUpperCase()}`;
const isVip = apiData.spent > 1000;
return <div>{fullName} {isVip ? '(VIP)' : ''}</div>;
};✅ 做法 B:充血领域模型(推荐)
定义一个 User 类(或带有方法的对象),封装逻辑。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// domain/User.ts
export class User {
constructor(
public id: string,
public firstName: string,
public lastName: string,
private totalSpent: number
) {}
// 业务逻辑内聚在模型中
get fullName(): string {
return `${this.firstName} ${this.lastName.toUpperCase()}`;
}
get isVip(): boolean {
return this.totalSpent > 1000;
}
}
// 转换层 (Adapter)
export function toUserDomain(dto: any): User {
return new User(dto.id, dto.first_name, dto.last_name, dto.spent);
}
// 组件内部 - 变得非常干净
const UserProfile = ({ user }: { user: User }) => {
return <div>{user.fullName} {user.isVip ? '(VIP)' : ''}</div>;
};5. 领域模型 vs 其他概念 (Comparison)
它和 Vuex/Redux 或 DTO 的区别:
| 概念 | 说明 | 区别 |
|---|---|---|
| DTO (Data Transfer Object) | 后端 API 返回的原始 JSON | 它是纯数据,没有行为(方法),且结构由后端决定。 |
| Domain Model | 业务实体 | 有数据也有行为,结构由前端业务需求决定。 |
| View Model (Store/State) | UI 状态 (Redux/Vuex) | 包含 UI 特有的状态(如 isLoading, isModalOpen),通常引用 Domain Model。 |
6. 总结 (The Wrap-up)
总的来说,前端引入领域模型是为了让核心业务逻辑‘独立生存’。它让我们从‘写页面的’转变为‘设计软件的’。
在项目中,通常会在 API 层和组件层之间加一层 Model 层,利用 TypeScript 的 Class 来封装数据和行为,这样不仅让组件代码更简洁,也大大方便了单元测试和后续维护。
