写好代码之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>
  }
 

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

相关推荐
GISer_Jing1 小时前
WebGL跨端兼容实战:移动端适配全攻略
前端·aigc·webgl
迦南giser1 小时前
前端性能——传输优化
前端
小白_ysf1 小时前
Vue 中常见的加密方法(对称、非对称、杂凑算法)
前端·vue.js·算法
2501_944448002 小时前
Flutter for OpenHarmony衣橱管家App实战:支持我们功能实现
android·javascript·flutter
人工智能训练7 小时前
【极速部署】Ubuntu24.04+CUDA13.0 玩转 VLLM 0.15.0:预编译 Wheel 包 GPU 版安装全攻略
运维·前端·人工智能·python·ai编程·cuda·vllm
会跑的葫芦怪8 小时前
若依Vue 项目多子路径配置
前端·javascript·vue.js
xiaoqi9229 小时前
React Native鸿蒙跨平台如何进行狗狗领养中心,实现基于唯一标识的事件透传方式是移动端列表开发的通用规范
javascript·react native·react.js·ecmascript·harmonyos
jin1233229 小时前
React Native鸿蒙跨平台剧本杀组队消息与快捷入口组件,包含消息列表展示、快捷入口管理、快捷操作触发和消息详情预览四大核心功能
javascript·react native·react.js·ecmascript·harmonyos
烬头882111 小时前
React Native鸿蒙跨平台实现二维码联系人APP(QRCodeContactApp)
javascript·react native·react.js·ecmascript·harmonyos
pas13611 小时前
40-mini-vue 实现三种联合类型
前端·javascript·vue.js