MVVM与事件总线的基本角色
在开发现代办公软件时,比如文档编辑器、表格处理工具或团队协作平台,界面逻辑和数据管理变得越来越复杂。MVVM(Model-View-ViewModel)模式通过分离视图和业务逻辑,让代码更清晰易维护。而事件总线则像一个“广播站”,让不同模块之间可以相互通信,而不必直接依赖。
为什么需要搭配使用?
假设你在做一个多人协同的办公文档系统。当用户A修改了某个单元格内容,用户B的界面需要实时更新。如果用传统方式,ViewModel之间可能要互相引用,导致耦合度高,一改全改。这时候引入事件总线,就能让修改数据的ViewModel发布一个“数据已变更”事件,其他监听该事件的ViewModel自动响应,无需直接调用对方。
实际场景中的代码示意
以下是一个简化的事件总线实现:
class EventBus {
constructor() {
this.events = {};
}
on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}
emit(event, data) {
if (this.events[event]) {
this.events[event].forEach(callback => callback(data));
}
}
}
const eventBus = new EventBus();
在 ViewModel 中使用:
// 数据修改的 ViewModel
class EditorViewModel {
updateCell(cellId, value) {
// 更新模型...
this.model.setCellValue(cellId, value);
// 通知其他人
eventBus.emit('cellUpdated', { cellId, value });
}
}
// 另一个同步显示的 ViewModel
class SyncViewModel {
constructor() {
eventBus.on('cellUpdated', (data) => {
this.updateDisplay(data.cellId, data.value);
});
}
}
带来的好处
这种组合方式让各个功能模块更加独立。比如新增一个“操作日志”面板,只需要监听相关事件,不需要改动原有的编辑逻辑。在大型办公软件中,团队分工明确,有人负责表格引擎,有人做界面交互,通过事件总线解耦,各自推进互不干扰。
同时,测试也变得更简单。ViewModel 不再强依赖其他对象,可以通过模拟事件来验证行为,提升开发效率。
注意事项
虽然灵活,但事件用多了容易失控。建议给事件命名加上模块前缀,比如 sheet:cellUpdated 而不是简单的 update,避免命名冲突。另外,记得在组件销毁时取消订阅,防止内存泄漏。