申明
博文中code例子是基于nej编写,假如你没运用过nej,也不会阻碍你明白代码。
实用场景
现实开辟中常碰到差别model对应多个view。用户经由过程 View 层来交互,View 偶然须要依据用户的数据更新 Model。还偶然 Model 须要更新其他的 Model,即一个model转变,触发一连串的view变化。
解决办法
这类状况,开辟者可以将一切对数据的操纵自力成一个数据层模块,集合治理数据相干的action。
nej这类机制的例子(不议论缓存),delete操纵作为明白例子util/cache/list.js
cache组件供应一个对外的action — _$deleteItem
/**
* 删除列表项
*
* 剧本举例
* ```javascript
* _cc._$deleteItem({
* key: '123'
* });
* ```
*
* @method module:util/cache/list._$$CacheList#_$deleteItem
* @param {Object} arg0 - 设置信息
* @property {String} key - 列表标识
* @property {String} id - 列表项标识
* @property {Object} data - 列表项数据信息
* @property {Object} ext - 须要回传的数据信息
* @return {Void}
*/
_pro._$deleteItem = function(_options){
_options = _u._$merge({},_options);
_options.onload = this.__deleteItem._$bind(this,_options);
this._$dispatchEvent('dodeleteitem',_options);
};
经由过程cache组件实例._$batEvent(‘dodeleteitem’, function(){});来发送ajax要求。要求所要options由外部组件挪用cache组件action时传入。平常只须要传入参数。onload回调运用dispatch事宜(可以支撑多个胜利后的回调)。
/**
* 删除列表项回调
*
* @protected
* @method module:util/cache/list._$$CacheList#__deleteItem
* @param {Object} arg0 - 要求信息
* @param {Boolean} arg1 - 是不是删除胜利
* @return {Void}
*/
_pro.__deleteItem = function(_options,_isok){
// 列表的例子中可以做一下cache相干的操纵
var _item,
_key = _options.key;
// sync memory
if (!!_isok){
var _id = _options.id;
_item = this._$getItemInCache(_id)||null;
this.__doRemoveItemFromList(_key,_id);
}
// callback
var _event = {
key:_key,
data:_item,
action:'delete',
ext:_options.ext
};
this._$dispatchEvent('onitemdelete',_event);
return _event;
};
经由过程cache组件实例._$batEvent(‘onitemdelete’, function(){}); 可以完成删除胜利以后的回调。差别views组件可以自力绑定事宜回调,如许代码解耦。一个view不须要的时刻,不须要改代码。
每一个cache组件都是一个单例实例。保证了在每一个差别的功用组件(view)中用到的是同一个。
每一类list cache组件都可以有本身的差别的crud,比方bookList.js
// $$CacheList == cache/list.js
var bookList = _t._$$CacheList._$allocate({
id: 'abc',
doloadlist: function (_options) {
// 从服务器加载列表
_j._$request(
'/api/list', {
data: _options.data,
onload: function (_list) {
_options.onload(_list);
}
}
);
},
dodeleteitem: function (_options) { _options由挪用cache.action处传入
// 从服务器删除数据项
_j._$request(
'/api/delete', {
data: _options.data,
onload: function (_item) {
_options.onload(_item);
}
}
);
}
});
return bookList;
nej对每一个list cache组件又笼统了一个基类cache/abstract.js
bookList.js继续abstract.js,根据api完成指定接口,返回list cache组件实例
list的数据层治理,可以笼统出通用的api,crud。所以nej把这类场景笼统成list.js。现实生产中,假如模块的数据层治理运用场景只要一个,也不须要在crud操纵中做cache相干操纵。平常只须要实例化成单例供应治理数据的action,dispatch相干事宜到差别的views组件。
// custom.js
_p._$$Custom = _k._$klass();
_pro = _p._$$Custom._$extend(_t._$$EventTarget);
_pro.__doSendRequest = function(key,options){
var conf = config[key];
// onload event
var onload = function(result){
if (!result||(''+result.code).indexOf('2')!==0){
onerror.call(this,result);
return;
}
// callback
var callback = options.onload||conf.onload||'success';
if (u._$isFunction(callback)){
callback.call(this,result.result);
}else if(u._$isString(callback)){
// dispatch在差别view组件中,绑定的事宜
this._$dispatchEvent(callback,result.result);
}
};
// options其他属性可以由挪用action _$checkUserName处传入
//data
//type:'json',
//method:'POST',
options.onload = onload._$bind(this);
request(options)
};
_pro._$checkUserName = function(options){
this.__doSendRequest('checkUserName', options);
};
return _p._$$Custom._$allocate({});
//在view组件中运用
// component1
define(['custom.js'], function(c){
c._$batEvent('onusernamecheckok', function(){
console.log('表单中username相干考证显现经由过程的款式');
});
// checkUserName DOM click事宜
var onCheck = function(
c._$checkUserName({
data: {xx: '王大锤'},
onload: 'onusernamecheckok'
});
);
});
// component2
define(['custom.js'], function(c){
c._$batEvent('onusernamecheckok', function(){
console.log('修正topbar的userName');
});
});
现在mv**库一片炽热的本日,也会也到多个view对应一个model的场景,facebook提出了一种解决方案单向数据流,单向数据流——就一个方向——当你须要插进去新的数据,流完整重新开始。他们把这类架构称为Flux。
Flux的大抵流程以下
经由过程如许设想,View的功用就会变得地道很多。它不须要体贴组件的状况和数据的操纵,只须要把交到它们手中的数据衬着花样化成用户可以明白的输出(HTML)。