# SimpleFramework **Repository Path**: mastertt/SimpleFramework ## Basic Information - **Project Name**: SimpleFramework - **Description**: 懒人自用简单版ccc项目框架 - **Primary Language**: TypeScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 7 - **Created**: 2021-08-05 - **Last Updated**: 2021-08-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 【懒人极简框架 VVFramework】 为什么取名叫VVFramework 全称 very vegetable framework 是一个很菜的框架[手动doge] ### 一、开门见山先丢链接 这个框架分两部分,插件和View管理模块,适用单场景开发的同学,理论上多场景也能用,没实验过[doge] 插件适用版本未知,.prefab文件结构一样应该都能用 View管理适用有bundle的版本cocos creator 2.4.x + TS https://gitee.com/Chou_nan/SimpleFramework.git ### 二、一点哔哔叨 从刚工作时的2.0.9,到现在的2.4.4,creator的成长可以说是非常的大了。在如此多的版本跨度里,其实我也就用过这俩[再次手动doge],中间跑去搞2dx-lua去了,最近才回到creator的怀抱。 又因为种种原因,一个小小菜鸡要担负起写框架的重任,属实害怕。在网上搜罗一圈大佬们写的真·框架,拿过来一看属实脑阔疼,只能感叹自己太菜了。直到看到**麒麟子大大**在介绍自己框架的文章中的一句话 **遵守“大道至简,实用至上”这两个基本原则。** 顿然醒悟,网上大佬的框架功能极其丰富,涉及到MVC,MVVM,一连串继承关系,还有跨引擎的公用框架,对我的需求来说就是在用航空母舰打蚊子,于是便决定了自己造个小苍蝇拍。 回顾自己不多的写BUG经验,确定主要解决以下痛点:【主要是懒,“懒是科技发展的动力”真是至理名言】 1. 能对脚本需要的节点自动导出,不用每次都手敲一堆声明(用过FGUI的自动导出脚本都说香) 2. 脚本挂载暴露的参数很多时,对开发时拖节点和往后冷不丁的维护都是噩梦,维护的痛懂的都懂 image-20210513131426035 3. 在onEnable和onDisable的里面成篇的on和off事件 ```typescript onEnable() { this.node.on('Event1', this.func1, this); // ...省去n行 this.node.on('Eventn', this.funcn, this); } onDisable() { this.node.off('Event1', this.func1, this); // ...省去n行 this.node.off('Eventn', this.funcn, this); } ``` ### 三、插件(针对痛点1) 对于痛点1网上有不少的插件,但为了结合我对于View管理的一些想法,所以对已有插件**ui-creator**进行了一丢丢改造。 #### 1、引入 拉下工程,将packages的prefab-ts-export导入到自己工程相同位置,不会的同学参照[官方文档](https://docs.cocos.com/creator/manual/zh/extension/install-and-share.html#%E5%85%A8%E5%B1%80%E6%89%A9%E5%B1%95%E5%8C%85%E8%B7%AF%E5%BE%84) #### 2、配置 ![1620837617353](./img/1620837617353.png) core:功能主要代码 template:自动导出文件的模板文件,导出的声明会放在红框两行注释之间,修改预制体再次导出时会根据这两行注释内的内容进行更新,**!!所以其他代码不要放在注释中!!这也是正则检索的标识不要修改!!** ![1620838412115](./img/1620838412115.png) export-conf.js:一些必要的配置,有需要导出的组件可自行在compMap修改 ![1620838189836](./img/1620838189836.png) #### 3、使用 因为针对的是单场景开发,所以导出功能只做了对prefab文件的,有需要可以自行拓展。 首先选中一个预制体,扩展->prefab-ts-export->导出(快捷键alt+s) ![1620838324941](./img/1620838324941.png) ### 四、View管理 #### 1、导入 a、引入assets/Framework文件夹(-js的不完整无法使用);b、引入SimpleFramework.d.ts #### 2、使用 这里的设计使用了bundle这一新特性,类似于FGUI的包,以功能模板为一个[bundle包](https://docs.cocos.com/creator/manual/zh/asset-manager/),里面放用到的图片和界面预制体等资源。![1620840682015](./img/1620840682015.png) a、打开界面 ```typescript onLoad() { vv.viewMgr.open('MenuView', '参数1', '参数2'); vv.viewMgr.open('MenuView', (tsComp: typeof vv.BaseView) => { // tsComp是界面的脚本 },'参数1', '参数2'); let tsComp = await vv.viewMgr.openSync('MenuView', '参数1', '参数2') let tsComp = vv.viewMgr.get('MenuView'); vv.viewMgr.close('MenuView'); vv.viewMgr.hide('MenuView'); } ``` 这里打开的界面需要配置在脚本 VVViewConfig.ts ```typescript /** 界面配置 */ const ViewConfig = { // BundlePath: bundle包的名字,PrefabPath: 预制体在包内的路径,preventTouch在界面打开前是否阻断触摸 'MenuView': {BundlePath: 'TestPanel', PrefabPath: 'MenuView', preventTouch: false}, 'ViewA': {BundlePath: 'TestPanel', PrefabPath: 'ViewA', preventTouch: false}, } ``` ts脚本需为预制体同名,可挂载可不挂载,挂载则必须挂在预制体根节点上,不挂载则会尝试挂载同名脚本。 b、vv.BaseView 要使用vv.viewMgr打开的View必须继承该类,并且额外增加了一些生命函数子类继承 ```typescript /** vv.view.open时 界面初始化 在 onLoad 和 onEnable执行之后 start执行之前 */ protected init(arg1, arg2, ...) {} /** vv.view.close时 界面被关闭 */ protected onClose() {} /** 可做一些UI初始化 init之后 */ protected _initUI() {} /** 可做初始化事件 _initUI之后 */ protected _initEvent() {} /** 打开其他界面被隐藏到后台时触发 */ public onToBack() {} /** 关闭其他界面后自动显示时触发 */ public onToFront() {} ``` **每个名字的View仅能打开一个**,再次打开时会将其放置在顶层 c、view的层级管理 目前大致分为(可在ViewZOrder.ts进行修改),将View的LayerOrder属性设置为相应的值改变层级,同一层级的View仅展示栈顶的(被隐藏的会调用*onToBack*),当上面的View关闭时,下面的自动显示(会调用*onToFront*) ```typescript /** view 层级 */ export const ViewZOrder = { MainView: 0, SubView: 200, PopView: 500, TopView: 900, TipsView: 999, } ``` ### 五、针对痛点2 当导出插件的配置 useAutoBind为true时,大家会发现导出声明的中装饰器变了,这里是仿造(官方貌似没支持,也可能我姿势不对)TS的 reflect-metadata 实现。 再配合View的*_autoBind*属性开启,在init()方法中可以直接使用导出的节点或组件。 ```typescript // @property(cc.Node) // public node1: cc.Node = null; // 变成了 @metadata("cc.Node") private node1: cc.Node = null; _autoBind = true; init() { consoel.log(this.node1) // 已经绑定对应节点 } ``` ### 六、针对痛点3 继承自BaseView的脚本,在open的时候会自动为形如*func_test*这种中间带下划线的函数注册事件,考虑到不挂载脚本的使用,也对Button进行了点击事件的注册 ```typescript @metadata("cc.Button") private _btn_test: cc.Button = null; onLoad() { // 自动注册是用vv.evtMgr.on,所以只有vv.evtMgr发送的才能触发 vv.evtMgr.emit('func_test', '参数1', '参数2'); } // 自动注册为事件,事件名跟函数名相同 func_test(arg1, arg2) { console.log('接受到事件', arg1, arg2); // 接受到事件 参数1 参数2 } // 这种不会注册为事件 funcTest2_ 这种也不会 _funcTest2() {} // 按钮点击事件对应 click + 按钮名(带下划线的会转大写) clickBtnTest() { console.log('_btn_test 被点击了'); } ``` ### 七、其他 *vv.resLoader*对资源加载进行了简单的封装 *vv.evtMgr*对自定义事件的简单实现 ### 八、结束 本菜也是第一写框架,应该说只是一些View管理,考虑不周和实现方式不优雅的地方希望大佬能帮我指导指导,希望能帮助到一些新同学,也算为社区贡献一丝绵薄之力。有想法或者问题的同学也可以找我一起讨论,感谢大家浏览。 ![1620843575394](./img/1620843575394.png)