JS 对象与数组的变化监听

MVVM重要一环的M到V的变化监听。研究了一些MVVM的框架。发现很多框架写的太过多复杂。

而且有些框架,把对象直接赋加很多它的私有属性,kendo 它把私有以_前缀来区分,knockout 和vue把对象直接转换成函数了。用起来感觉怪怪的。感觉已经不是自己当初的数组或对象了

所以想动手自己写一套数据模型监听。

一、我想做的事情是监听Object 或Array的变化就行,

二、我不会去污染原始的Object 和Array .意思当你创建一个Object或Array 模型,返回给你的还是你原来的对象或数组。

属性的监听

第一种是利用方法来更新对象的值,来监听属性的变化

第二种是利用属性访问器,defineProperty 创建set,get 方法来监听属性的变化。

defineProperty  在IE8没有完全支持,像司徒正美的avalon 框架,他采用了vbscript  来解决




我用的是第二种,先把代码贴出来吧。详细讲解


我是利用事件源的深度跟踪,来监听所有属性的变化,与很多框架不同的地方,很多框架,比如vue 它每一个属性都会创建一个dep 对象,来通知,这样感觉管理起来太麻烦。

下面是来监听各属性的的用法,一眼看过,很清楚,属性监听写法简简单单,包括后面,我怎么去利用这个。来写一个m到v的数据呈现.

JS 对象与数组的变化监听_第1张图片

那么下面开始怎么写,先对象和数组自带的方法包装一下,方便快捷使用

JS 对象与数组的变化监听_第2张图片

第一步创建一个事件监听方法,这个监听对象是面向开发者的,

path 字段 是用来跟踪属性的所在位置,即它是谁的属性,它在哪里发生变化了。

subscribe 是一个事件监听对象。通过on(name,callback) 添加,通过trigger(name,args...)触发

下面会重点讲解 newSubscribe 这个方法。


JS 对象与数组的变化监听_第3张图片

下面创建一个监听模型,

Object的处理很简单。直接返回就行。

Array 相对还要重写监听一下它的一些能改变内部值的方法。

JS 对象与数组的变化监听_第4张图片


创建一个访问器,这里是关键。

用defineProperty 去复制源对象或数组的属性,以set,get 方式去访问属性,在set,里面来监听用户的行为。

当值发生变化,去通知监听它的事件。

这里面。每一个Observer对象都会有一个subscribe 的监听对象,

SetValue 方法里面,当值是Object 或Array的时候,会重新new  一个Observer 对象。

并且用当前的监察对象Subscribe.newSubscribe(name) 创建一 个新的监听对象,并且把当前所处位置告诉它。

然后调用 _listernerData 方法,去临听这个新的subscribe 对象 

当子Observer 模型对象下面任何属性只要调用trigger,都会触发* 事件,*事件会调用它父级Subscribe对象的trigger 事件。 往上面一级通知,这样不段的向自己的上级汇报,说我这里面发生变化了,最终由最高管理者,来决定,你发生变化了,我该去处理了

代码片段,不清楚可以滚动到上面去看DepSubscribe 的方法:

 newSubscribe: function (name)
                {
                    var subscribe = new DepSubscribe();
                    subscribe.path = name;
                    this._listernerData(subscribe);
                    return subscribe;
                },
                getPath:function(name)
                {
                    name = name || "";
                    return   this.path != "" ? this.path + "." + name : name;
                }

  trigger:function()
                {
                    var args = array_common.from(arguments);
                    args[0] = this.getPath(args[0]);
                    if (this.getPath()=="")
                    {
                        args[0] = args[0] + ".change";
                    }
                    this.subscribe.trigger.apply(this.subscribe, args);
                },

   _listernerData: function (subscribe) {
                    var that = this;
                    subscribe.on('*', function (name) {
                        that.trigger.apply(that,arguments);  // 当子模型下面的属性有变化,再往上一级通知
                    });
                },

*,on("*",callback). 前面讲了,当参数是*,就会监听模型所有的属性变化


JS 对象与数组的变化监听_第5张图片


JS 对象与数组的变化监听_第6张图片

最后,利用这个模型监听对象,开发一个简单Model到View 的单向绑定的例子,模型的值发生变化了,会自动呈现到页面,

data.age=新值 页面中引用了表达式的textNode会自动更新值

data.list.push(值)的时候,页面dx-for 元素会自动追加div元素

data.list.splice ,页面dx-for 元素会自动删除集合中索引位置的子元素


JS 对象与数组的变化监听_第7张图片

JS 对象与数组的变化监听_第8张图片

JS 对象与数组的变化监听_第9张图片

代码例子下载地址:点击打开链接

喜欢的请大家多多支持和交流.

你可能感兴趣的:(JS 对象与数组的变化监听)