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的主要内容,如果未能解决你的问题,请参考以下文章
MVVM Light:在 XAML 中添加 EventToCommand 而不使用 Blend、更简单的方法或片段?
Android 上的 Kotlin:如何在片段中使用数据库中的 LiveData?
使用Architecture Components构建的应用程序是否使其成为“MVVM”,如果是,应用程序的哪些部分与哪个MVVM层相关?