import { isString, isObject, merge } from '../util';
import dirtyActions from '../action/dirty';
import { modelActions } from '../action/event';
/**
* Model基类
*
* @class Model
*/
class Model {
__dirty = true;
_updateTime = 0;
constructor(option = {}, parentModel, globalModel, global) {
this.option = option;
this.parentModel = parentModel;
this.globalModel = globalModel;
this.global = global;
}
/**
* 标记为脏,将被更新
*
* @param {Object} action 触发dirty的事件
*/
dirty(action) {
let { globalModel } = this;
// console.log(`${this.type}_${this.index}准备设置为dirty!`, action);
if (!action || this.shouldModelDirty(action, this, globalModel)) {
// console.log(`${this.type}_${this.index}设置为了dirty!--------------`, action);
this.__dirty = true;
globalModel && globalModel !== this && globalModel.dirty(this, action);
this.global.dispatchAction(this, modelActions.willUpdate, { action, model: this });
return true;
} else {
return false;
}
}
/**
* 是否需要设置为dirty
*
* @param {Object} action 触发dirty的事件
* @param {Object} model 组件model
* @param {Object} globalModel globalModel
* @returns {boolean} 是否需要标记dirty
*/
shouldModelDirty(action, model, globalModel) {
return true;
}
/**
* 子类需实现update方法
*/
update() { }
beforeUpdate() { }
afterUpdate() { }
/**
* 内部实际调用的update方法
*
* @param {bool} force 是否强制更新
* @private
*/
__update(force) {
if (this.isDirty() || force) {
this.beforeUpdate(force);
this.update(force);
this.__dirty = false;
this._updateTag = ++this._updateTime + '|' + this.id; // 设置tag
// console.log(`${this.type}_${this.index}更新了!依赖我的也会更新`, this.supports);
this.global.dispatchAction(this, modelActions.didUpdate, { model: this, option: this._option });
this.afterUpdate(force);
}
}
/**
* 是否为dirty
*
* @returns {boolean} 是否为dirty
*/
isDirty() {
return this.__dirty;
}
/**
* 获取实际option
*
* @param {string} [key] 获取option内的key属性,若不传返回全部option
* @returns {any} 返回key对应的属性
*/
get(key) {
if (key) {
return this._option[key];
} else {
return this._option;
}
}
/**
* 设置option
* TODO 设置的option与之前相同时
*
* @param {string|Object} key 属性名或者属性对象
* @param {any} [value] 属性内容
*/
set(key, value) {
if (isString(key) && (this._option[key] !== value || typeof value === 'object')) {
this._option[key] = value;
this.dirty({
type: dirtyActions.setOption,
payload: {
[key]: value,
}
});
} else if (isObject(key)) {
merge(this._option, key, true);
this.dirty({
type: dirtyActions.mergeOption,
payload: key
});
}
}
}
export default Model;