MVVM和MVC

332 阅读4分钟

前言

最近,在和一个同事闲聊的时候被问到MVC和MVVM的区别,说实话,这是一个面试题大军中非常常见的一员,但是之前可能是只是背一下,并没有深入的了解过,所以在被同事问到之后,我突然语塞了,不知道该如何作答,当时感觉还是挺羞愧的,所以为了弥补我这方面的漏洞,我深入的了解了一下MVVM和MVC

MVC

首先说一下MVC,MVC分为三层,Model(模型层)、View(视图层),Controller(控制层),其实简单来说,MVC可以总结为一句话,Controller负责将Model的数据渲染在View中(就是如此简单)。但是仔细理解起来还是有些费时间的,下面我们就一一讲解下MVC这三层

  1. View层是最上面的一层(显示层),是直接面对用户的,它将操作界面提供给用户
  2. Controller层是中间的一层(操作层), 是控制层,主要是用于处理数据,根据View层不同的指令来"选取"Model层的数据,然后对其进行相应的操作,返回相应的数据
  3. Model层是最下面的一层(数据层),即程序所需要的数据等
三层紧密联系,但是却又互不干扰,只通过接口进行交互,

三者之间的关系是user --> view ---> controller --->Model-->view(这里我没有找一张图附上),所以view层和Model层是没有直接进行交互的,而是通过controller层进行交互的

MVC的优点

下面我只说一些常见的

  1. 低内聚

    这个词相信大家都不会陌生,在软件工程中我们总是说高耦合,低内聚,所谓的低内聚到底是什么意思呢,低内聚表示各个模块之间的联系要尽量的少

  2. 可维护性高

    由于将视图层和业务逻辑层分开,所以我在维护上也变得更加容易

MVC的缺点

至于MVC的缺点,其实说起来可能比较高大上一点,能兴趣的可以看下

  1. 增加了系统结构的复杂性,毕竟现在一个项目是拆分成三层的,所以在结构上肯定会比较复杂
  2. view层对model的数据低效率访问,因为view层只能通过controller层对model的数据进行访问

MVVM

讲完MVC了,我们再来讲讲MVVM,首先,大家肯定会有疑问,为什么有了MVC,还会出现MVVM呢,其实原因是MVC是允许Model和View直接通信的,当随着业务量变大的时候,这块的逻辑依赖肯定会变得复杂,同时这要是MVVM模式设计的出发点, 下面我们来看看MVVM,MVVM也是分为三层,View(视图层), Model(数据层), ViewModel(中间层)

  1. View层,这个和上面MVC中的view层的作用是一样的
  2. Model层,也是数据层
  3. ViewModel层,这层其实只是起一个桥梁的作用,主要是用于将View层的修改同步到Model,把Model层的数据显示到View层

MVVM的中心思想(数据驱动)

  1. 响应式
  2. 模板解析
  3. 渲染

响应式

什么是响应式呢,又是怎么实现响应式的呢 首先响应式就是通过数据驱动渲染View层的界面,它是怎么做到的呢,像我们正常修改数据,怎么能通过到view层我们的数据改变了呢,其实底层主要是通过一个函数实现的,就是Object.defineProperty()实现的

var people = {
    name: 'pwz',
    age: 18
}
var vm = {}

var key
var value 
for(let i in people) {
    (function(key){
        Object.defineProperty(vm, key, {
            get: function() {
                return people[key]
            },
            set: function(newVal) {
                people[key] = newVal
            }
        })
    })(key)
    
}

模板解释

模板的本质上就是字符串,但是模板上还有一系列的逻辑指令等等,如果我们在普通的html上写一个v-for的指令,这肯定是不生效的,所以我们在这里要介绍一个函数,render函数,(render函数的底层是with函数,但是这个函数现在已经不推荐使用了),通过render函数我们最终生成一个虚拟DOM

渲染

如何将虚拟DOM渲染成html呢,此时分为两种情况,第一种就是初次渲染的时候,第二种就是数据更新的时候,此时会调用updateComponent方法

vm._update(vnode){
  const prevVnode = vm._vnode
  vm._vnode = vnode
  if (!prevVnode){
    vm.$el = vm.__patch__(vm.$el,vnode)
  } else {
    vm.$el = vm.__patch__(prevVnode,vnode)
  }
}

function updateComponent(){
  vm._update(vm._render())
}

首先会读取虚拟dom,判断其是否为空,如果为空,则为初次渲染,将虚拟dom全部渲染到页面,若不为空,则是数据发生了修改,通过响应式我们可以监听到这一情况,使用diff算法完成新旧对比并修改

MVC和MVVM的区别

  1. MVVM的View和Model是不能直接交互的
  2. MVVM通过数据来驱动视图,用户只需要关心数据的变化即可