写好代码之MVVC架构模式

MVC

  • 视图 (View):用户界面
  • 控制器 (Controller):业务逻辑
  • 模型 (Model):数据保存,渲染数据源

例如:

  1. view 收到dom点击指令到 Controller;
  2. Controller 完成业务逻辑后,要求Modal改变数据状态;
  3. Modal将新数据发送到View,用户得到反馈;

代码实现以Backbone.js 计数器示例:

html 复制代码
    <!DOCTYPE html>
<html>
<head>
  <title>Backbone MVC Counter</title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.1/underscore-min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.4.0/backbone-min.js"></script>
</head>
<body>
  <div id="app">
    <div>count: <span id="count-display">0</span></div>
    <button id="increment-btn">加+1</button>
  </div>

  <script>
    // 1. Model (数据 + 逻辑)
    const CounterModel = Backbone.Model.extend({
      defaults: {
        count: 0
      },
      increment: function() {
        this.set({ count: this.get("count") + 1 }); // 更新数据
      }
    });

    // 2. View (UI + 事件监听)
    const CounterView = Backbone.View.extend({
      el: "#app", // 挂载点
      events: {
        "click #increment-btn": "handleIncrement" // 监听按钮点击
      },
      initialize: function() {
        this.model = new CounterModel(); // 初始化 Model
        this.listenTo(this.model, "change", this.render); // 监听 Model 变化
        this.render(); // 初始渲染
      },
      handleIncrement: function() {
        this.model.increment(); // 调用 Model 方法修改数据
      },
      render: function() {
        // 手动更新 DOM
        this.$("#count-display").text(this.model.get("count"));
        return this;
      }
    });

    // 启动应用
    new CounterView();
  </script>
</body>
</html>

MVC 数据流(Backbone.js)

  1. 用户点击按钮View 捕获事件,调用 handleIncrement
  2. View 调用 Model 方法increment() 修改数据。
  3. Model 触发 change 事件View 监听到变化,手动更新 DOM(render())。

特点

  • 手动 DOM 更新render() 方法)。
  • Model 和 View 解耦,但需要显式监听数据变化。
  • Controller 逻辑分散在 View 中(Backbone 没有严格独立的 Controller)。

MVVM

MVVM出现原因解决:

分离关注点,分离视图与业务逻辑

  • MVC中需要手动控制View和Model之间的双向数据绑定的繁琐逻辑,如上Backbone.js的示例,Controller分散在View中代码耦合度高,维护困难,测试困难;

  • MVVM引入视图模型(ViewModel)自动双向数据绑定,即修改定义的响应数据(vue:refreact:state),自动反应到数据在视图上的变化;让开发者只需要关注业务逻辑,不需要关心view和Model的绑定关系,由于ViewModel(业务处理数据逻辑)与View分离,可能独立于视图测试,提高测试效率。

Vue (MVVM 模式)

在 MVVM 中:

  • Modelref/reactive 数据。
  • View :模板(<template>)。
  • ViewModel<script setup> 中的逻辑(处理数据绑定和事件)。
代码实现
javascript 复制代码
<script setup>
import { ref } from 'vue'

// Model (数据)
const count = ref(0)

// ViewModel (逻辑)
const handleIncrement = () => {
  count.value += 1 // 修改数据,Vue 自动更新视图
}
</script>

<!-- View (模板) -->
<template>
  <div>count: {{ count }}</div>
  <button @click="handleIncrement">加+1</button>
</template>
MVVM 数据流(Vue)
  1. 用户点击按钮View 触发 @click 事件。
  2. ViewModel 执行 handleIncrement → 修改 count
  3. Vue 自动检测数据变化 → 更新 DOM(无需手动操作)。

特点

  • 自动 DOM 更新(响应式系统)。
  • 双向绑定 (表单输入可用 v-model)。
  • ViewModel 作为中间层,解耦 Model 和 View。

MVC vs. MVVM 对比

特性 Backbone.js (MVC) Vue (MVVM)
数据绑定 手动更新 DOM (render()) 自动(响应式系统)
代码量 较多(需手动监听和渲染) 较少(声明式模板)
职责分离 Model + View(Controller 混合在 View) Model + View + ViewModel(清晰分层)
适用场景 需要精细控制 DOM 的场景 快速开发数据驱动型应用

总结

通过MVC与MVVM比较,介绍了为什么MVC后会出现MVVM架构模式,主要是考虑开发效率,代码可维护和测试性考虑;分离关注点利用VM(视图模型),数据驱动视图,无需手动关注数据与视图双向绑定,日常编写Vue和React代码时,需要有意识的将VM(事件回调处理和数据请求等处理)与View(渲染内容)做隔离解耦,如下面:

javascript 复制代码
  const App = ()=>{
       const [count,setCount] = useState(0)   
       
       /*VM*/
       const handleClick = ()=>{
           setCount(preCount=> preCount+=1)
       }
       
       /*View*/
       return <div >
         {{count}}
          /* 不推荐,没有让VM 与 View 分离 */
           <button onClick={()=>{
             setCount(preCount=> preCount+=1) ❌
           }}>点击</button>
           
           <button onClick={handleClick}>点击</button> ✅
      </div>
  }
 

希望对你有帮助!如果有进一步问题,欢迎讨论 😊

相关推荐
天官赐福_9 分钟前
vue2的scale方式适配大屏
前端·vue.js
江城开朗的豌豆9 分钟前
CSS篇:前端经典布局方案:左侧固定右侧自适应的6种实现方式
前端·css·面试
Carlos_sam11 分钟前
Openlayers:flat样式介绍
javascript
我儿长柏必定高中11 分钟前
Promise及使用场景
前端
无名友11 分钟前
HTML — 浮动
前端·css·html
0xJohnsoy12 分钟前
React中的this详解
前端
the_one13 分钟前
🚀「v-slide-in」+ 瀑布流实战指南:Vue 高级滑入动画一键实现,页面质感瞬间拉满!
前端·javascript·css
ZL不懂前端13 分钟前
微前端介绍
前端
Lear14 分钟前
uniapp&微信小程序markdown&latex
前端
江城开朗的豌豆14 分钟前
CSS篇:CSS选择器详解与权重计算全指南
前端·css·面试