mv**中,用数据层解决多个view对应不同model的问题

来源:转载

说明

博文中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 memoryif (!!_isok){var _id = _options.id;_item = this._$getItemInCache(_id)||null;this.__doRemoveItemFromList(_key,_id);}// callbackvar _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.jsvar 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 eventvar onload = function(result){if (!result||(''+result.code).indexOf('2')!==0){onerror.call(this,result);return;}// callbackvar 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'}););});// component2define(['custom.js'], function(c){c._$batEvent('onusernamecheckok', function(){console.log('修改topbar的userName');});});

如今mv**库一片火热的今天,也会也到多个view对应一个model的场景,facebook提出了一种解决方案单向数据流,单向数据流——就一个方向——当你需要插入新的数据,流完全重新开始。他们把这种架构称为Flux。

Flux的大致流程如下

通过这样设计,View的功能就会变得纯粹许多。它不需要关心组件的状态和数据的操作,只需要把交到它们手中的数据渲染格式化成用户能够理解的输出(HTML)。


分享给朋友:
您可能感兴趣的文章:
随机阅读: