做前端开发,尤其是用 Vue 或 Knockout 这类框架时,MVVM 模式几乎是家常便饭。很多人一上来就把数据往 ViewModel 里堆,结果 Model 层形同虚设,最后代码越来越乱,改个接口字段都能牵一发而动全身。
Model 层到底该干啥?
先说清楚,Model 不是简单地把 API 返回的数据存一下。它真正的职责是:封装业务数据、处理数据转换、统一接口通信。你可以把它理解成一个“数据管家”——外面不管怎么变,只要交给 Model,它就能返回干净、结构清晰的数据。
比如你做一个电商项目,后端返回的商品信息可能叫 prod_name、price_yuan,但你在页面上要展示的是“商品名称”和“价格(元)”。如果每个组件都自己去转换,那后期维护简直噩梦。这时候,Model 层就应该把这些字段映射好,对外提供统一的 name 和 price。
一个干净的 Model 长什么样?
以 Vue 项目为例,假设你要获取用户信息。别急着在组件里写 axios.get('/api/user'),先把逻辑收进 Model。
class UserModel {
constructor(data) {
this.id = data.user_id;
this.name = data.user_name;
this.email = data.user_email;
this.role = this.formatRole(data.user_role);
}
formatRole(role) {
const map = { admin: '管理员', user: '普通用户', guest: '访客' };
return map[role] || '未知角色';
}
static async fetch(userId) {
const res = await axios.get(`/api/user/${userId}`);
return new UserModel(res.data.data);
}
}
组件里只需要关心:“我要一个用户”,然后调用 UserModel.fetch(123),拿到的就是格式化好的对象。哪天后端改了字段名,你只需要改 Model 里的构造函数,不用动视图代码。
复杂点的场景怎么办?
比如订单系统,一个订单关联用户、商品、物流信息。这时候可以拆出多个 Model,并建立关联。
class OrderModel {
constructor(data) {
this.id = data.order_id;
this.amount = data.total_price;
this.user = new UserModel(data.user_info);
this.items = data.items.map(item => new ProductModel(item));
this.shippingStatus = this.parseStatus(data.logistics_status);
}
parseStatus(status) {
return status === 1 ? '已发货' : '待发货';
}
}
这样,View 层只需要渲染 order.user.name 或遍历 order.items,完全不用知道后端接口长啥样。数据结构变了?改 Model 就行,UI 几乎不动。
别让 Model 变成大杂烩
有人图省事,把所有 API 请求全塞进一个 Model 文件,最后几千行代码,谁都不敢动。正确的做法是按业务拆分:UserModel、OrderModel、ProductModel 各司其职,必要时通过 Service 层统一管理请求逻辑。
另外,Model 不一定非得是 class。如果你的项目简单,用纯函数也行:
function normalizeUser(raw) {
return {
id: raw.user_id,
name: raw.user_name,
level: `LV${raw.exp_level}`
};
}
关键是保持数据处理逻辑集中、可复用。别让每个组件都重复做同样的格式化工作。
MVVM 的优势就在于分工明确。把 Model 写好,你会发现项目越往后做越轻松,加新功能时,老代码不会成为绊脚石。