前端常见架构(MVC和MVVM)

发布于 2024-03-02  113 次阅读


复杂的软件必须有清晰合理的架构,否则无法开发和维护

一、MVC

什么是MVC

MVC(Model-View-Controller)是最常见的软件架构之一
MVC是模型(Model)、视图(View)和控制器(Controller)的缩写,下面有一幅图 可以表明他们之间的关系

MVC如何工作

MVC的一般交互流程就是:

  1. 用户操纵 View,触发Controller上的一个事件。
  2. Controller通过事件让Model通知View进行更新。

接下来通过一些简单的代码演示一个简易的MVC模型,首先是Model层

var myApp = {} // 首先创建这个应用对象
    myApp.Model = function () {
      // model的实现
      var val = 0 // 假设当前模型数据为val 当然实际可能有更多
      // 定义一些行为
      this.add = function (v) {
        val += v
      }
      this.sub = function (v) {
        val -= v
      }
      this.getVal = function () {
        return val
      }

      // 实现一个观察者模式
      var self = this,
        views = []

      this.register = function (view) {
        views.push(view)
      }

      this.notify = function () {
        // 通知View更新
        for (var i = 0; i < views.length; i++) {
          views[i].render(self)
        }
      }
    }

view层

myApp.View = function (controller) {
      var $num = $('#num'), // 假设页面上有这样几个节点
        $incBtn = $('#incBtn'),
        $decBtn = $('#decBtn')

      this.render = function (model) {
        $num.innerText = model.getVal()
      }

      // 给按钮绑定事件
      $incBtn.click = controller.increase
      $decBtn.click = controller.decrease
    }

Controller层

myApp.controller = function () {

      var model = null,

        view = null

      // 初始化函数

      this.init = function () {

        // 初始化Model和View

        model = new myApp.Model()

        view = new myApp.View(this)

        // 让view在model中注册 这样model就可以通知View进行更新

        model.register(view)

        mdoel.notify()

      }

      // 通知Model更新数值并让Model更新View视图

      this.increase = function () {

        model.add(1)

        model.notify()

      }

      this.decrease = function () {

        model.sub(1)

        model.notify()

      }

    }

可以看到这里实现了一个简单的MVC模型 用户可以通过操作View节点事件来通知Controller,Controller通过Model来通知View视图进行Render

MVC的优缺点

优点

  • 耦合性低
  • 重用性高
  • 部署快
  • 可维护性高
  • 有利于软件工程化管理

缺点

  • 没有明确的定义
  • 不适合中小型的应用
  • 增加系统结构和实现的复杂性
  • 试图与控制器建过于紧密的连接
  • 视图对模型数据的低效率访问

二、MVVM

什么是MVVM

MVVM = Model-View-ViewModel,与 MVC、MVP 不同的就在于最后一个部件,换成了 ViewModel(VM)

同样,这里也实现一个简单的MVVM模型

// model
var data = {
    val: 0
};

// view
<div id="myapp">
    <div>
        <span>{{ val }}rmb</span>
    </div>
    <div>
        <button v-on:click="sub(1)">-</button>
        <button v-on:click="add(1)">+</button>
    </div>
</div>

// controller
new Vue({
  el: '#myapp',
  data: data,
  methods: {
    add(v) {
        if(this.val < 100) {
            this.val += v;
        }
    },
    sub(v) {
        if(this.val > 0) {
            this.val -= v;
        }
    }
  }
});

MVVM的实现原理:

MVVM的实现主要是三个核心点:

  • 响应式:vue如何监听data的属性变化
  • 模板解析:vue的模板是如何被解析的
  • 渲染:vue模板是如何被渲染成HTML的

这其中最主要的为vue如何监听data的属性变化

响应式

对于MVVM来说,data一般是放在一个对象当中,就比如这样:

var obj = {
             name: 'xxxx',
             age: 25
         }

当我们访问或修改obj的属性的时候,比如:

console.log(obj.name)  //访问
         obj.age = 22    //修改

但是这样的操作vue本身是没有办法感知到的,那么应该如何让vue知道我们进行了访问或是修改的操作呢?
那就要使用Object.defineProperty

var vm = {}
        var data = {
            name: 'zhangsan',
            age: 20
        }

        var key, value
        for (key in data) {
            (function (key) {
                Object.defineProperty(vm, key, {
                    get: function () {
                        console.log('get', data[key]) // 监听
                        return data[key]
                    },
                    set: function (newVal) {
                        console.log('set', newVal) // 监听
                        data[key] = newVal
                    }
                })
            })(key)
        }

通过Object.defineProperty将data里的每一个属性的访问与修改都变成了一个函数,在函数get和set中我们即可监听到data的属性发生了改变。

最后更新于 2024-03-02