切图崽的自我修养-[MVVM] 如何监听数据变化
数据监听
vm模式的核心就是数据变化驱动视图更新,其中关键的一点就是,我们如何能知道数据发生了变化?
发布-订阅模型
通过事件的发布/监听的模式来实现数据监听. 即数据变化后,发布者会触发自定义的某个事件比如valueChage
,然后订阅者捕获到这个事件后,实现后续处理(值判断/视图更新/其他自定义逻辑
). 这其实就是最简单的事件处理的机制
待补充
GET/SET
监测数据的变化还有一种简单且较为完美的实现,并且目前十分火热的Vm框架Vue也是应用了这种方式.那就是Es5中对对象的新增的扩展方法Object.defineProperty()
. 它带来了无数可能性.通过对对象的属性设置改方法,我们也能轻易的实现数据变化后的逻辑处理.
先来简单看一看Object.defineProperty()的简单使用
Object.defineProperty(obj, prop, descriptor)
var obj = {}; Object.defineProperty(obj, "name", { enumerable: true, configurable: true, get: function () { console.log('get#'); return name; }, set: function (newValue) { console.log('set#'); name = newValue + "~~~"; } }); obj.name = 'Xie' // set# console.log(obj.name); //get# Xie~~~ obj.name = 'Min' // set# console.log(obj.name); //get# Min~~~
参数介绍:
value:属性的值
writable:如果为false,属性的值就不能被重写
get: 一旦目标属性被访问就会调回此方法,并将此方法的运算结果返回用户
set:一旦目标属性被赋值,就会调用此方法
configurable:如果为false,则任何尝试删除目标属性或修改属性以下特性(writable, configurable, enumerable)的行为将被无效化
enumerable:是否能在for...in循环中遍历出来或在Object.keys中列举出来
P.s writeble/value
不能和get/set
共存,因为object不允许有两种访问机制存在.
实现数据驱动
正是因为get/set这种特性,我们就能通过设置set方法来完成数据变化->视图更新
的逻辑
<input id='input'> <p id="output"></p>
var obj = {}; $('#input').on('input',function(){ obj.data = $(this).val(); }); Object.defineProperty(obj, "data", { enumerable: true, configurable: true, get: function () { return data; }, set: function (newData) { data = newData; $('#output').text(data); } });
数据变化驱动视图更新
是MVVM模式中VM的核心逻辑,这种模式下的任何时候,我们都不应该直接以操纵DOM节点的方式来改变视图, 而是必须通过改变数据状态的方式,驱动数据状态变化来改变视图(具体方式上面已经提到了,捕获valueChage事件/SET
等) Angular/Vue/Avalone/等等之类的MVVM框架,就是封装并优化了这一个步骤.