mv**中,用數據層解決多個view對應不一樣model的問題

說明

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

相關文章
相關標籤/搜索