博文中code例子是基于nej编写,若是你没使用过nej,也不会妨碍你理解代码。javascript
实际开发中常遇到不一样model对应多个view。用户经过 View 层来交互,View 有时须要根据用户的数据更新 Model。还有时 Model 须要更新其余的 Model,即一个model改变,触发一连串的view变化。java
这种状况,开发者能够将全部对数据的操做独立成一个数据层模块,集中管理数据相关的action。
nej这种机制的例子(不讨论缓存),delete操做做为理解例子util/cache/list.js
cache组件提供一个对外的action -- _$deleteItemgit
/** * 删除列表项 * * 脚本举例 * ```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事件(能够支持多个成功后的回调)。github
/** * 删除列表项回调 * * @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不须要的时候,不须要改代码。ajax
每一个cache组件都是一个单例实例。保证了在每一个不一样的功能组件(view)中用到的是同一个。
每一类list cache组件均可以有本身的不一样的crud,例如bookList.jsjson
// $$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组件。api
// 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)。架构