cocoscreator的mvc框架

简易轻量级MVC框架,适用于中小型项目使用。后续会拓展lightMVC_ex内容来适应大型项目的开发。这套轻量级MVC框架可以帮助开发者组织代码,以及业务结构,让项目更好维护和拓展,提高开发效率。examples目录下有完整的例子Demo。


节点功能

Facade:全局控制类,持有对MVC各层的管理对象。原则上来说,除了初始化框架调用init和运行第一个场景外,都不应该引用和调用Facada中的任何接口和属性。该类是个全局的单例对象,包含几个重要的接口如下:

/** * 初始化框架配置*@param{boolean}debug是否是调试状态*@param{cc.Size}designResolution设计分辨率*@param{boolean}fitHeight是否高适配*@param{boolean}fitWidth是否宽适配*/publicinit(debug:boolean, designResolution:cc.Size, fitHeight:boolean, fitWidth:boolean):void;/** * 运行场景*@param{{new(): BaseMediator}}mediator场景mediator类型,类类型。*@param{{new(): BaseScene}}view场景mediator类型,类类型。*@param{Object}data自定义的任意类型透传数据。(可选)*@param{()=>void}cb加载完成回调.*/publicrunScene(mediator:{new():BaseMediator}, view:{new():BaseScene}, data?:any, cb?:()=>void):void;

Model:数据对象,用于处理数据逻辑以及存储数据,常用来与服务器做数据交互,同时通过消息通知View层刷新显示。主要接口如下:

/**Model初始化时会调用的接口,可以用来初始化一些数据*/publicinit():void;/** * 发送消息接口,当数据变化时需要调用此接口发送消息刷新View层。*@param{string}noti消息名称*@param{Object}data消息数据*/publicsendNoti(noti:string, data?:any):void;/**清理接口,子类可以实现清理逻辑*/publicclear():void;

View:显示层,根据业务逻辑及数据显示,同时处理用户输入,通过事件与其他层交互。主要接口如下:

/**View创建时会被调用,子类可以重写*/publicinit():void;/** * 发送UI事件,逻辑层接收事件处理逻辑。*@param{string}event事件名称*@param{Object}body事件参数*/publicsendEvent(event:string, body?:any):void;/**关闭当前的界面*/publiccloseView():void;/**关闭所有弹出的界面*/publiccloseAllPopView():void;/**当界面被关闭时会被调用,子类可以重写该方法*/publiconClose():void;/**子类覆盖,返回UI的prefab路径,默认是空节点*/publicstaticpath():string;

Mediator:逻辑层中介者,负责接收Model层通知来刷新View层显示,同时还要接收View层事件来处理用户输入,并通过Command处理数据层数据。主要接口如下:

/** * 初始化接口,此时视图还没有创建,如果想操作视图view请在viewDidAppear函数中进行。*@param{Object}data自定义的任意类型透传数据。(可选)*@override**/publicinit(data?:any):void;/** * 视图显示后会调用的接口*@override*/publicviewDidAppear():void;/** * 绑定UI事件,接收view层派发的事件*@param{string}name事件名称*@param{(any)=>void}cb事件回调*@param{BaseMediator}target回调绑定对象*/publicbindEvent(name:string,cb:(body:any)=>void, target:BaseMediator):void;/** * 注册消息监听*@param{string}noti通知key值*@param{(data: any)=>void}cb通知监听的回调函数*@param{Object}target回调绑定的对象*/publicregisterNoti(noti:string,cb:(data:any)=>void, target:any):void;/** * 发送消息通知*@param{string}noti通知key值*@param{Object}body消息传递的参数*/publicsendNoti(noti:string, body:any):void;/** * 发送命令接口*@param{{new (): BaseCommand}}cmd命令类*@param{Object}data命令参数*/publicsendCmd<TextendsBaseCommand>(cmd:{new():T}, data?:any):void;/** * 打开新场景*@paramdata{Object} data 自定义的任意类型透传数据。(可选)*/publicrunScene(mediator:{new():BaseMediator}, view:{new():BaseScene}, data?:any):void;/** * 返回上一场景*@returns{boolean}是否存在上一个场景*/publicbackScene():boolean;/** * 打开view界面*@param{{new(): BaseMediator}}mediator界面mediator类型,类类型。*@param{{new(): BaseView}}viewview 场景mediator类型,类类型。*@param{Object}data自定义的任意类型透传数据。(可选)*/publicpopView(mediator:{new():BaseMediator}, view:{new():BaseView}, data?:any):void;/** * 添加层级*@param{{new(): BaseMediator}}mediator界面mediator类型,类类型。*@param{{new(): BaseView}}viewview 场景mediator类型,类类型。*@param{number}zOrder层级。(可选)*@param{Object}data自定义的任意类型透传数据。(可选)*/publicaddLayer(mediator:{new():BaseMediator}, view:{new():BaseView}, zOrder?:number, data?:any):void;/**获取model对象*/publicgetModel<TextendsBaseModel>(model:{new():T}):T;/**销毁接口*/publicdestroy():void;

使用方式

初始化框架:

//调试模式为false、设计分辨率为1080*2048、宽适配。Facade.getInstance().init(false,cc.size(1080,2048),false,true);

注册model数据对象:

//如果需要数据层,那么应该首先将所有需要的model在开始就都注册上。Facade.getInstance().registerModel(PlayerModel);

运行第一个场景:

//运行第一个场景时调用Facade的runScene接口,传入要运行的Mediator和Scene,还可选传入参数。Facade.getInstance().runScene(DefaultSceneMediator, DefaultScene,"测试参数999");

原则上说,除了上述三步需要引用Facade外,后面场景运行起来后就不需要再调用Facade了,在MVC的不同层级做对应的逻辑处理,父类接口都做了支持。

场景运行后,可以在场景Mediator中创建层级view,或者pop出view。Layer view与pop view的区别就是,他们是两个管理器在进行管理,我们认为Layer是场景内初始化创建并且不会关闭的view界面,而pop view是可以随时打开或者关闭的view界面,当然具体怎么使用可以灵活处理。例如在DefaultSceneMediator中:

/** * 创建一个常驻的view界面FirstView  * this.addLayer是BaseMediator中提供的基础功能接口(更多接口可以查看源码)。 * 层级为1,并且传入参数:this._data**/this.addLayer(FirstMediator, FirstView,1,this._data);

View层的UI节点操作接口。在View里有个成员属性ui,该界面的UI节点会在初始化时自动初始化到这个成员属性上,在操作UI节点时可以通过这个属性进行操作,该属性类型是UIContainer,常用接口是getNode和getComponent,示例代码如下:

//获取node节点letcloseBtnNode=this.ui.getNode("close_btn");closeBtnNode.on(cc.Node.EventType.TOUCH_END,this.closeAllView,this);//获取Component组件letdesLabel=this.ui.getComponent("des_label",cc.Label);desLabel.string="test";

View层与Mediator层的事件交互。Mediator直接持有View的引用,所以可以直接调用View中的接口,而View与Mediator就需要通过事件(Event)来进行交互了。首先需要在Mediator中注册监听:

this.bindEvent(FirstView.OPEN_B, (str:string)=>{//todo something...},this);

然后在View中通过sendEvent接口发送事件来通知Mediator:

//第一个参数是事件名称,第二个参数是传递的参数。this.sendEvent(FirstView.OPEN_B,"BBB");

Mediator操作Model数据。在Mediator中可以通过getModel接口获取到指定的Model对象,通过直接引用来读取Model中的数据。而在修改数据的时候有两种方式,一种是通过Model的引用直接进行修改,这种情况大多是比较简单直接修改某个数值等;另一种比较复杂,比如要获取多个Model的数据进行复杂的逻辑操作并且修改多个值的情况,这种就适合将逻辑封装到一个命令(Command)中,通过发送命令来处理数据,这样可以减少Mediator中逻辑复杂度和耦合度。例子如下:

//直接通过引用进行修改的情况letplayerModel=this.getModel(PlayerModel);this.view.setLevelDisplay(playerModel.getPlayerLv());//通过命令进行操作的情况this.sendCmd(UpdateExpCommand, exp);

Model数据修改通知View刷新逻辑。大多数情况下,Model用来处理纯数据逻辑和与服务器交互的数据接口,当数据有变化时我们希望通知View刷新显示,这是我们只能通过抛出消息通知来告诉Mediator,然后通过Mediator来修改View显示,首先需要在Mediator中注册消息通知:

this.registerNoti(Notification.UPDATE_EXP_FINISH, ()=>{//todo something ...},this);

然后我们在Model中通过发送这个消息通知来告诉Mediator:

//该接口第二个参数可以传递参数this.sendNoti(Notification.UPDATE_EXP_FINISH);

Mediator与Mediator之间的交互很简单,就是使用上面介绍Model向Mediator发送通知的方式。

其他

简单的交互规则和接口调用介绍就这么多,还有就是代码结构的组织也很重要,这个就是看每个人或者项目的合理安排了,毕竟也是仁者见仁,智者见智的事情。同时在examples目录下有完整的例子Demo

lightMVC目前仅适合中小型项目使用,过于复杂的大型项目可能应付起来就会有些吃力,不过后续会继续维护并拓展到lightMVC_ex中来支持大型项目开发,lightMVC会始终保持简单轻量。

最后框架中有什么问题或者需要改进的问题欢迎反馈。

来源地址 https://github.com/yue19870813/lightMVC

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容