为什么架构不是枯燥的图表
想象一下你在建造一栋房子。你可以随意堆砌砖块,浇筑混凝土,然后希望结构不会倒塌。或者,你可以精心设计地基、承重墙和楼板。在JavaScript开发中也是如此:没有深思熟虑的架构,你的项目就会变成"意大利面条式代码",修改一个函数就会破坏整个应用程序。
架构模式并非书本上的枯燥理论。它们是经过实战检验的方案,可以帮助你:
- 保持清醒,当项目扩展到50,000行代码时。
- 快速定位错误,因为代码被划分为逻辑模块。
- 添加功能,而不用担心破坏任何东西。
在本文中,我们将探讨JavaScript应用程序的五个关键模式:从经典的MVC到模块化方法。开始吧!
MVC(Model-View-Controller):所有模式之祖
MVC是Web开发的金标准。该模式将应用程序分为三层:
- Model — 数据和业务逻辑(CRUD、验证)。
- View — 用户看到的界面(HTML、渲染)。
- Controller — 中介:接收用户请求并更新Model或View。
以下是代码中的样子:
// Modelclass UserModel { constructor() { this.users = []; }
addUser(user) { this.users.push(user); }
getUsers() { return this.users; }}
// Viewclass UserView { render(users) { const list = document.getElementById('user-list'); list.innerHTML = users.map(u => `<li>${u.name}</li>`).join(''); }}
// Controllerclass UserController { constructor(model, view) { this.model = model; this.view = view; }
addUser(name) { this.model.addUser({ name, id: Date.now() }); this.view.render(this.model.getUsers()); }}
// 使用const model = new UserModel();const view = new UserView();const controller = new UserController(model, view);controller.addUser('Alice');controller.addUser('Bob');何时在JavaScript中使用MVC? 非常适合中型和大型SPA(单页应用程序)。但要小心:如果View严重依赖Model,该模式会变成"Massive View Controller"——控制器会膨胀得不成比例。
MVP(Model-View-Presenter):严格的监督者
MVP是MVC的演进,其中Presenter接管了View的所有逻辑管理。与MVC不同,MVP中的View是一个被动的"哑"层。它只负责显示数据并将事件传递给Presenter。
// Model(与MVC中相同)class UserModel { constructor() { this.users = []; } addUser(user) { this.users.push(user); } getUsers() { return this.users; }}
// View — 被动接口class UserView { constructor() { this.list = document.getElementById('user-list'); this.addButton = document.getElementById('add-btn'); }
bindAddUser(handler) { this.addButton.addEventListener('click', () => { const name = prompt('请输入姓名:'); if (name) handler(name); }); }
render(users) { this.list.innerHTML = users.map(u => `<li>${u.name}</li>`).join(''); }}
// Presenter — 应用程序的大脑class UserPresenter { constructor(model, view) { this.model = model; this.view = view; this.view.bindAddUser(this.handleAddUser.bind(this)); this.view.render(this.model.getUsers()); }
handleAddUser(name) { this.model.addUser({ name, id: Date.now() }); this.view.render(this.model.getUsers());