源码解析1

119 阅读2分钟

小结一下上面源码,以绑定position为例,调用Factory.addGetterSetter后做了三件事

  1. 添加setPosition方法,若Node类有定义setPosition,则直接执行,没有定义则调用_setAttr方法,更新node.attrs.position的值,触发positionChange事件,有的地方会像这样监听on('positionChange', xxx),最后调用到Shape::drawScene重绘
  2. 添加getPosition方法,同上,若Node类有定义getPosition,则直接执行,没有则绑定function
  3. 模拟getter和setter方法
var GET = 'get',
  SET = 'set';

export const Factory = {
  /**
   * addGetterSetter 模拟es6的getter和setter
   * @param constructor Node类
   * @param attr 'width'
   * @param def '0'
   * @param validator def参数的数据类型检查器
   * @param after 设置属性之后的回调事件
   */
  addGetterSetter(constructor, attr, def?, validator?, after?) {
    // 添加getXXX方法
    Factory.addGetter(constructor, attr, def);
    // 添加setXXX方法
    Factory.addSetter(constructor, attr, validator, after);
    // 添加getter和setter方法
    Factory.addOverloadedGetterSetter(constructor, attr);
  },
  // 设置getter
  addGetter(constructor, attr, def?) {
    // method = getWidth
    var method = GET + Util._capitalize(attr);

    // 为Node类的原型对象添加getWidth方法,这里有个很关键的判断,如果Node类上定义了getWidth方法直接使用,没定义则使用下面的函数
    constructor.prototype[method] =
      constructor.prototype[method] ||
      function () {
        var val = this.attrs[attr];
      	// 初始化时,获取def,例:addGetterSetter(Node, 'width', 0, getNumberValidator())
      	// 更新时,获取val,例:node.width(10) 
        return val === undefined ? def : val;  
      };
  },
  // 设置setter
  addSetter(constructor, attr, validator?, after?) {
    // method = setWidth
    var method = SET + Util._capitalize(attr);

    // 如果Node类中没有定义setWidth,则调用overWriteSetter重写setWidth
    if (!constructor.prototype[method]) {
      Factory.overWriteSetter(constructor, attr, validator, after);
    }
  },
  // 重写setter,绑定到原型对象上
  overWriteSetter(constructor, attr, validator?, after?) {
    // method = setWidth
    var method = SET + Util._capitalize(attr);
    constructor.prototype[method] = function (val) {
      // 检查更新时传入值得数据类型,不符合则抛错
      if (validator && val !== undefined && val !== null) {
        val = validator.call(this, val, attr);
      }

      // 更新node.attrs上属性,触发on('widthChange', xxx)事件,最终调用到Shape::drawScene重绘
      this._setAttr(attr, val);

      // 事后的回调,上面绑定filters时有用到
      if (after) {
        after.call(this);
      }

      return this;
    };
  },
  
  // ...
  
  // 设置getter和setter方法
  addOverloadedGetterSetter(constructor, attr) {
    var capitalizedAttr = Util._capitalize(attr),
      setter = SET + capitalizedAttr,  // setWidth
      getter = GET + capitalizedAttr;  // getWidth

    // 为Node类的原型对象设置width方法,有传参则为setter,未传参则为getter
    constructor.prototype[attr] = function () {
      // node.width(10)
      if (arguments.length) {
        this[setter](arguments[0]);
        return this;
      }
      // node.width()
      return this[getter]();
    };
  },
  
  // ...
};