每次面试被问到"MVC和MVVM有什么区别"时,你是不是也只会背"一个带Controller一个带ViewModel"?作为经历过无数场技术面试的老前端,我发现90%的候选人都在重复教科书定义,却说不清这些模式在实际项目中的真实表现。今天我们就用最直观的方式——可运行的代码对比,来破解这个经典面试题。
在开始编码前,我们先搭建一个公平的对比环境。假设要实现一个经典计数器功能:点击按钮时数字增加,分别用三种方式实现:
提示:所有示例都使用现代ES6+语法,建议在CodePen或本地开发环境实时运行代码
先准备基础HTML结构:
html复制<!-- 公用HTML结构 -->
<div class="counter-container">
<span class="counter-value">0</span>
<button class="increment-btn">+1</button>
</div>
让我们先用最原始的方式实现MVC架构。注意观察各层之间的调用关系:
javascript复制// Model层 - 处理数据逻辑
class CounterModel {
constructor() {
this.value = 0;
}
increment() {
this.value += 1;
return this.value;
}
}
// View层 - 处理UI展示
class CounterView {
constructor() {
this.valueEl = document.querySelector('.counter-value');
this.buttonEl = document.querySelector('.increment-btn');
}
updateValue(newValue) {
this.valueEl.textContent = newValue;
}
bindIncrement(handler) {
this.buttonEl.addEventListener('click', handler);
}
}
// Controller层 - 协调Model和View
class CounterController {
constructor(model, view) {
this.model = model;
this.view = view;
this.view.bindIncrement(this.handleIncrement.bind(this));
}
handleIncrement() {
const newValue = this.model.increment();
this.view.updateValue(newValue);
}
}
// 初始化应用
const app = new CounterController(new CounterModel(), new CounterView());
关键观察点:
现在用Vue 3的Composition API实现相同功能,注意ViewModel如何自动处理数据绑定:
html复制<div id="app" class="counter-container">
<span class="counter-value">{{ count }}</span>
<button class="increment-btn" @click="increment">+1</button>
</div>
<script>
const { ref } = Vue;
const app = Vue.createApp({
setup() {
const count = ref(0);
const increment = () => {
count.value += 1;
};
return { count, increment };
}
});
app.mount('#app');
</script>
对比发现:
{{ count }}自动同步数据到视图@click直接关联方法,无需手动addEventListenerReact虽然不完全符合经典MVVM,但Hooks提供了类似的开发体验:
jsx复制import { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const increment = () => {
setCount(prev => prev + 1);
};
return (
<div className="counter-container">
<span className="counter-value">{count}</span>
<button className="increment-btn" onClick={increment}>
+1
</button>
</div>
);
}
React的特点:
通过三种实现方式的对比,我们可以总结出关键差异:
| 特性 | MVC | MVVM |
|---|---|---|
| 数据流向 | 单向显式调用 | 双向自动绑定 |
| DOM操作 | 手动更新 | 框架自动处理 |
| 代码量 | 较多 | 较少 |
| 学习曲线 | 平缓 | 较陡峭 |
| 适用场景 | 传统多页面应用 | 现代SPA应用 |
| 典型框架 | Backbone.js | Vue, Angular |
实际项目选型建议:
选择MVC:
选择MVVM:
在技术面试中,关于MVC/MVVM常有几个误区需要澄清:
React是MVVM吗?
双向绑定是必须的吗?
哪种模式性能更好?
面试时可重点准备: