dojo源码阅读之dojo/Stateful

Posted yang_chuanlong

tags:

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

dojo/Stateful是dojo中的一个基类,提供了能够观测对象属性变化的功能,Stateful 使用文档

其基本用法如下:

var s = new Stateful(foo:8)
s._fooSetter = function(value)
  this.foo = value;
;
s.watch("foo", function(name, oldValue, newValue)
   console.log(`foo的值由$oldValue变为$newValue`)
)

执行 s.set("foo", 9),  s._fooSetter就会被调用, 同时控制台会输出: ”foo的值由8变为9“

Stateful是如何做到上述功能的呢,Stateful.set方法, 可以看到当调用 Stateful实例的set方法时,set方法会根据要传入的name计算出setter方法, 如set('foo', 9)会找到_fooSetter方法并执行,如果使用了watch方法观察foo的变化,那么对应的callback就会被调用。

watch是如何实现的呢。Stateful.watch方法。以下面代码为例

 s = new Stateful()
 watchFun1 = function(name, oldValue, newValue)
     console.log(`fun1 is invoked`);
 ;
 watchFun2 = function(name, oldValue, newValue)
     console.log(`fun2 is invoked`);
 ;
 s.watch("foo", watchFun1)
 s.watch("foo", watchFun2)

watch方法的实现步骤大致如下:

1, 定义_watchCallbacks 方法(一个Stateful实例只会被定义一次)。

    this._watchCallbacks  = function(name, oldValue, value)

            .....//根据name找到对应的listener函数并执行。如foo对应的watchFun1和watchFun2.

     

2, this._watchCallbacks._foo = [watchFun1, watchFun2]

_changeAttrValue方法

_changeAttrValue方法用来直接改变Stateful实例的属性,而不属性对应的setter方法。

如s._changeAttrValue("foo", 9)会直接设置s.foo为9而不调用s._fooSetter, 如果使用s.set("foo", 9)则会调用。

什么情况下会用到_changeAttrValue方法呢,当Stateful实例有两个互相link的属性时。如s.bar = s.foo * 2;

当s.bar改变时s.foo也要变,而s.foo改变时s.bar也要跟着改变。这样就会形成一个无限循环。如:

 s = new Stateful(
        foo: 1
    );
    //bar = foo * 2
    s._fooSetter = function(name, value) 
        this.foo = value;
        this.set("bar", value * 2);
        console.log("s._fooSetter is invoked");
    

    s._barSetter = function(name, value) 
        this.bar = value;
        this.set("foo", value / 2);
        console.log("s._barSetter is invoked");
    

如果使用_changeAttrValue就可以避免这个问题。如下:

s._fooSetter = function(value) 
        this.foo = value;
        this._changeAttrValue("bar", value * 2);
        console.log("s._fooSetter is invoked");
    

    s._barSetter = function(value) 
        this.bar = value;
        this._changeAttrValue("foo", value / 2);
        console.log("s._barSetter is invoked");
     

你可以像上面例子中直接Stateful实例化一个对象,但一个更好的方式是继承Stateful来实现一个子类再实例化对应的对象, 如下:

MyStateful = new declare([Stateful], 
        foo:1,
        _fooSetter: function(value)
            this.foo = value;
            this._changeAttrValue("bar", value * 2);
        ,
        bar: 2,
        _barSetter: function(value)
            this.bar = value;
            this._changeAttrValue("foo", value / 2);
        
    );

    s = new MyStateful();


以上是关于dojo源码阅读之dojo/Stateful的主要内容,如果未能解决你的问题,请参考以下文章

dojo源码阅读之declare

dojo源码阅读之declare

dojo/_base/lang源码分析

提高阅读源代码的效率 转

Dojo 学习笔记 之 Dojo hitch&partial

Tornado源码阅读(一) --- IOLoop之创建ioloop