sumeru
Version:
A Realtime Javascript RIA Framework For Mobile WebApp
156 lines (140 loc) • 5.09 kB
JavaScript
var runnable = function(fw){
(function(fw){
// sense 对像空间
if (fw.sense)return fw.sense;
var sense = fw.addSubPackage('sense');
/**
* runSenseContext执行的方法周期内,将创建inspector,用于监视用户处理逻辑中的getter方法的执行.
* 在用户处理逻辑完成后自动销毁,使在runSenseContext方法周期外的用户逻辑代码,不再重复监听getter.
*
* @param customClosure {function} 用户方法,在此方法中使用的所有sense对像,将被监听.
*/
sense.__reg('runSenseContext',function(customClosure){
/*
* 监视器,用于监视customClosure的执行过程中,对sense对像的调用.
*/
sense.__reg('_senseInspector', function(senseObjInstance, key){
senseObjInstance.addObserver(key, customClosure);
}, true);
//FIXME 如果用户逻辑中存在异步调用或setTimeout,将导到依赖关系丢失。
// 触发用户处理过程
customClosure();
//用户代码执行完成后,销毁inspector
sense.__reg('_senseInspector', function(){}, true);
});
var Sense = {
/**
* 根据键名取得键值.如果触发时间点在runSenseContext的方法周期中,将向外部检查器注册当前context中,对某个key的依赖.
* @param key
* @returns {any}
*/
get:function(key){
sense._senseInspector && sense._senseInspector(this, key);
if( typeof this.container != 'object') {
console.warn('no container error in sense get on line 38 '+key);
return;
}
return this.container[key];
},
/**
* 设置或修改键值
* @param key {string}
* @param value {any}
*/
set:function(key, value){
this.container[key] = value;
if(this.observer.length != 0){
for(var i = 0, l = this.observer.length; i < l; i++){
if(this.observer[i].key != key || this.toBeCommited.some(function(item){
return item(this.observer[i]);
},this)){
continue;
}
this.toBeCommited.push((function(that, observerItem){
return function(checkObserver){
if(arguments.length === 0 ){
//fw.dev('exec customCloser', observerItem.customClosure.length);
observerItem.customClosure.call(that, key);
}else{
return checkObserver == observerItem;
}
};
})(this, this.observer[i]));
}
}
},
/**
* 确认修改session,并自动重新触发对相关依赖的用户方法.
* @returns {Boolean}
*/
commit:function(){
var toBeCommited = this.toBeCommited;
if(toBeCommited.length === 0){
return true;
}
var tapped_blocks = [];
fw.controller.__reg('_tapped_blocks', tapped_blocks, true);
for (var i = 0, l = toBeCommited.length; i < l; i++){
toBeCommited[i]();
}
//每个Controller的render方法会保证局部渲染一定等待主渲染流程完成才开始。
fw.controller.__load('reactiveRender')(tapped_blocks);
toBeCommited.length = 0;
},
addObserver:function(key, customClosure){
// 去重
for(var i = 0, l = this.observer.length; i < l; i++){
if(this.observer[i].key === key && this.observer[i].customClosure == customClosure ){
return; //两个函数不会相等的,不知道谁写的,但这行永远不会执行 FIXME ,上面的函数改成toString后会造成session.get在两个onload是相等的bug
}
}
this.observer.push({
key : key,
customClosure : customClosure
});
},
removeObserver:function(func){
for(var i = 0, l = this.observer.length; i < l; i++){
if(this.observer[i].customClosure === func){
this.observer.splice(i, 1);
return;
}
}
},
cleanObserver:function(){
this.observer.length = 0;
this.toBeCommited.length = 0;
}
};
/**
* 创建继承自sense对像的类.
* @param constructor {function} 目标类的构造方法
* @param proto {object} 用于constructor的prototype,
* 如果提供,则使用该对像做为继承prototype并附加方法,
* 如果不提供,则使用constructor.prototype
* @returns {function} 继承处理过的构造方法
*/
sense.__reg('extend',function(constructor,proto){
// 创建一个当前目标构造方法的代理方法,用于初始化sence对像。
var proxy_constructor = (function(){
return function(){
// 对像属性
this.toBeCommited = [];
this.observer = [];
this.container = {};
// 执行正真的构造方法
constructor.apply(this,arguments);
};
})(constructor);
// copy sense的方法至目标构造方法的prototype
proxy_constructor.prototype = fw.utils.cpp(proto || constructor.prototype,Sense);
return proxy_constructor;
});
})(fw);
}
//for node
if(typeof module !='undefined' && module.exports){
module.exports = runnable;
}else{
runnable(sumeru);
}