小结一下上面源码,以绑定position为例,调用Factory.addGetterSetter后做了三件事
- 添加setPosition方法,若Node类有定义setPosition,则直接执行,没有定义则调用_setAttr方法,更新node.attrs.position的值,触发positionChange事件,有的地方会像这样监听on('positionChange', xxx),最后调用到Shape::drawScene重绘
- 添加getPosition方法,同上,若Node类有定义getPosition,则直接执行,没有则绑定function
- 模拟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]();
};
},
// ...
};