MVVM

Posted lhh520

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MVVM相关的知识,希望对你有一定的参考价值。

MVVM由以下三个内容组成

View:视图模板

Model:数据模型

ViewModel:作为桥梁负责沟通View和Model,自动渲染模板

在JQuery时期,如果需要刷新UI时,需要先取到对应的DOM再更新UI,这样数据和业务的逻辑就和页面有强耦合。

在MVVM中,UI是挺数据驱动的,数据一旦改变就会刷新相应的UI,UI变化也会改变相应的数据。这种方式在开发中只需要关心数据的变化,不用直接去操作DOM。并且可以将一些可复用的逻辑放在一个ViewModel中,多个View复用这个ViewModel。

在 MVVM 中,最核心的也就是数据双向绑定,例如 Angluar 的脏数据检测,Vue 的数据劫持,React数据绑定

 

 Angluar 的脏数据检测

当触发了指定事件后进入脏数据检测,这时期会调用$digest循环遍历所有的数据观察者,判断当前值是否和先前的值有区别,如果检测到变化的话,会调用$watch函数,然后再次调用$digest循环直到发现没有变化。所以这个过程可能会循环几次,一直到不再有数据变化发生后,将变更的数据发送到视图,更新页面展现。如果是手动对 ViewModel 的数据进行变更,为确保变更同步到视图,需要手动触发一次“脏值检测”。

脏数据检测虽然需要每次去循环遍历查看是否有数据变化,存在低效的问题,与Vue的双向绑定原理不同,但是脏数据检测能够同时检测出要更新的值,再去统一更新UI,这样也可以减少操作DOM的次数。

 

Vue 的数据劫持

Vue2.0版本内部使用了Object.defineProperty()来实现数据与视图的双向绑定,体现在对数据的读写处理过程中。即Object.defineProperty()中定义的数据set、get函数。

使用Object.defineProperty()实现Vue2.0双向绑定的小demo:

 <div id="app">
      <input type="text" id="input">
      <span id="text"></span>
 </div>
 var obj = {};
 Object.defineProperty(obj, ‘prop‘, {
     get: function() {
         return val;
     },
     set: function(newVal) {
         val = newVal;
         document.getElementById(‘input‘).value = val;
         document.getElementById(‘text‘).innerhtml = val;
     }
 });
 document.addEventListener(‘keyup‘, function(e) {
     obj.prop = e.target.value;
 });

但仅仅如此还是不够的,还需要在适当的时候添加发布订阅。

技术分享图片

如上所述,vue.js通过Object.defineProperty()来劫持各个属性的setter,getter。再结合发布者-订阅者的方式,

发布消息给订阅者,触发相应的监听回调。通过Directives指令去对DOM做封装,当数据发生变化,会通知指令去修改对应的DOM,数据驱动DOM的变化。vue.js还会对操作做一些监听(DOM Listener),当我们修改视图的时候,vue.js监听到这些变化,从而改变数据。这样就形成了数据的双向绑定。

 

技术分享图片

 

以上是关于MVVM的主要内容,如果未能解决你的问题,请参考以下文章

Android MVVM在哪里存储数据?

MVVM Light:在 XAML 中添加 EventToCommand 而不使用 Blend、更简单的方法或片段?

Android 上的 Kotlin:如何在片段中使用数据库中的 LiveData?

使用Architecture Components构建的应用程序是否使其成为“MVVM”,如果是,应用程序的哪些部分与哪个MVVM层相关?

Dagger MVVM - ViewModel注入为null

使用 NavController 从片段导航到另一个片段