写好代码之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:ref;react:state),自动反应到数据在视图上的变化;让开发者只需要关注业务逻辑,不需要关心view和Model的绑定关系,由于ViewModel(业务处理数据逻辑)与View分离,可能独立于视图测试,提高测试效率。

Vue (MVVM 模式)

在 MVVM 中:

  • Model :ref/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>
  }
 

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

相关推荐
Ken_11152 小时前
小体积附件下载正常,大附件下载异常
javascript
变与不变8062 小时前
jQuery怎么使用
前端·javascript
神膘护体小月半2 小时前
flex 布局的 order 属性
前端·css
paopaokaka_luck2 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
仰望.3 小时前
vue 表格组件 vxe-table 树表格懒加载支持拖拽排序的详细用法
前端·javascript·vue.js·vxe-table
前端 贾公子3 小时前
vite-plugin-uni-manifest 升级指南
前端
小码哥_常3 小时前
iPhone 用户传了张 HEIC,我的前端崩了
前端
小码哥_常3 小时前
你发的原图可能暴露你家地址——聊聊图片 EXIF 隐私
前端
java1234_小锋3 小时前
【技术专题】CSS3 网页技术 - CSS3 优先级
前端·css·css3
鸿蒙开发4 小时前
共享 Schema 与 SchemaFactory
前端·后端·harmonyos