MVC与MVVM的区别是什么?

MVC与MVVM的区别是什么?

技术背景

在软件开发中,架构模式对于组织代码和管理软件的复杂度至关重要。MVC(Model-View-Controller)和MVVM(Model-View-ViewModel)是两种常见的架构模式。MVC模式最早在20世纪70年代被提出,最初应用于桌面图形用户界面(GUI)开发,后来在Web开发中也被广泛使用。而MVVM模式则是在MVC的基础上发展而来,它起源于Martin Fowler的Presentation Model,在WPF/Silverlight开发中得到了广泛应用,随着Web技术的发展,也逐渐在Web开发中流行起来。

实现步骤

MVC实现步骤

  1. 定义模型(Model):模型负责存储应用的数据和业务逻辑,它不依赖于视图和控制器。
  2. 创建视图(View):视图负责展示数据给用户,处理用户的交互。
  3. 实现控制器(Controller):控制器作为视图和模型之间的桥梁,接收视图的用户输入,调用模型进行数据处理,然后更新视图。

MVVM实现步骤

  1. 定义模型(Model):与MVC中的模型类似,负责存储应用的数据。
  2. 创建视图(View):视图负责展示数据和处理用户交互。
  3. 实现视图模型(ViewModel):视图模型是视图的抽象表示,它暴露视图所需的数据和命令,负责处理视图的状态和逻辑,通过数据绑定与视图进行交互。

核心代码

MVC示例代码(以简单的待办事项应用为例)

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// 模型
class TodoModel {
constructor() {
this.todos = [];
}

addTodo(todo) {
this.todos.push(todo);
}

getTodos() {
return this.todos;
}
}

// 视图
class TodoView {
constructor() {
this.todoList = document.getElementById('todo-list');
this.addButton = document.getElementById('add-button');
this.input = document.getElementById('todo-input');
}

render(todos) {
this.todoList.innerHTML = '';
todos.forEach(todo => {
const li = document.createElement('li');
li.textContent = todo;
this.todoList.appendChild(li);
});
}

bindAddTodo(handler) {
this.addButton.addEventListener('click', () => {
const todo = this.input.value;
if (todo) {
handler(todo);
this.input.value = '';
}
});
}
}

// 控制器
class TodoController {
constructor(model, view) {
this.model = model;
this.view = view;

this.view.bindAddTodo(this.addTodo.bind(this));
this.updateView();
}

addTodo(todo) {
this.model.addTodo(todo);
this.updateView();
}

updateView() {
const todos = this.model.getTodos();
this.view.render(todos);
}
}

// 初始化
const model = new TodoModel();
const view = new TodoView();
const controller = new TodoController(model, view);

MVVM示例代码(以简单的用户信息编辑页面为例)

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// 模型
struct User {
var name: String
var email: String
}

// 视图模型
class UserViewModel {
private var user: User

var name: String {
didSet {
user.name = name
nameChanged?()
}
}

var email: String {
didSet {
user.email = email
emailChanged?()
}
}

var nameChanged: (() -> Void)?
var emailChanged: (() -> Void)?

init(user: User) {
self.user = user
self.name = user.name
self.email = user.email
}

func saveProfile() {
// 模拟保存操作
print("Profile saved: \(user.name), \(user.email)")
}
}

// 视图
class UserView {
var viewModel: UserViewModel

init(viewModel: UserViewModel) {
self.viewModel = viewModel

viewModel.nameChanged = { [weak self] in
self?.updateName()
}

viewModel.emailChanged = { [weak self] in
self?.updateEmail()
}
}

func updateName() {
print("Name updated: \(viewModel.name)")
}

func updateEmail() {
print("Email updated: \(viewModel.email)")
}

func saveButtonTapped() {
viewModel.saveProfile()
}
}

// 初始化
let user = User(name: "John Doe", email: "[email protected]")
let viewModel = UserViewModel(user: user)
let view = UserView(viewModel: viewModel)

最佳实践

MVC最佳实践

  • 保持控制器的简洁:控制器应该只负责协调视图和模型之间的交互,避免在控制器中包含过多的业务逻辑。
  • 使用依赖注入:通过依赖注入的方式将模型和视图注入到控制器中,提高代码的可测试性和可维护性。

MVVM最佳实践

  • 保持视图模型的独立性:视图模型应该不依赖于具体的视图,只负责处理视图的状态和逻辑,方便进行单元测试。
  • 合理使用数据绑定:通过数据绑定实现视图和视图模型之间的自动更新,减少手动更新视图的代码。

常见问题

MVC常见问题

  • 控制器过于臃肿:随着应用的复杂度增加,控制器可能会包含大量的业务逻辑,导致代码难以维护。
  • 视图和模型之间的耦合度较高:视图和模型之间的交互可能会导致它们之间的耦合度较高,不利于代码的复用和扩展。

MVVM常见问题

  • 学习曲线较陡:MVVM模式引入了视图模型的概念,对于初学者来说可能需要一定的时间来理解和掌握。
  • 性能问题:过多的数据绑定可能会导致性能问题,尤其是在处理大量数据时。

综上所述,MVC和MVVM各有优缺点,在实际开发中需要根据项目的需求和特点选择合适的架构模式。


MVC与MVVM的区别是什么?
https://119291.xyz/posts/difference-between-mvc-and-mvvm/
作者
ww
发布于
2025年6月24日
许可协议