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的数据呈现.

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


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

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

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

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



下面创建一个监听模型,

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

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


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

用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). 前面讲了,当参数是*,就会监听模型所有的属性变化





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

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

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

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




猜你喜欢

转载自blog.csdn.net/lookbackward/article/details/78365737