博文中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)。架構