一堆公有类太多,new来new去不方便,cocos creator ts+loC+装饰器框架

框架未命名

感谢大佬mzzik提供想法。
思路来源 springboot + midway
这是使用ts+loc+装饰器来开发的框架,方便大家管理公用与公用参数

由于cocos creator不支持元数据,全部使用map 来模拟实现

重要代码组成


// Inject 注入类

// @libs/di/Inject.ts

import 'reflect-metadata';

import Container from './Container';// 使用 id 定义模块后,需要使用 id 来注入模块

export function Inject(id?:any): PropertyDecorator {

    return (target: Object, propertyKey: string | symbol) => {

        var a1 = id.name;

        const GetObj:symbol= Container.getObj(a1)

        const _dependency = Container.get(GetObj);

        target[propertyKey] = _dependency;

    };

}


//Service 注册类

// @libs/di/Service.ts

import Container from './Container';

// import "reflect-metadata";

interface ConstructableFunction extends Function {

    new(): any;

}// 自定义 id 初始化

export function Service (id: string): Function;

// 作为单例初始化

export function Service (singleton: boolean): Function;

// 自定义 id 并作为单例初始化

export function Service (id: string, singleton: boolean): Function;

export function Service (idOrSingleton?: string | boolean, singleton?: boolean): Function {

return (target: ConstructableFunction) => {

    let _id;

    let _singleton;

    let _singleInstance;

   

    if (typeof idOrSingleton === 'boolean') {

        _singleton = true;

        _id = Symbol(target.name);

    } else {

        // 判断如果设置 id,id 是否唯一

        if (idOrSingleton && Container.has(idOrSingleton)) {

            throw new Error(`Service:此标识符(${idOrSingleton})已被注册.`);

        }

   

        _id = idOrSingleton || Symbol(target.name);

        _singleton = singleton;

    }

    // Reflect.defineMetadata('cus:id', _id, target);

    if (_singleton) {

        _singleInstance = new target();

    }

    let id1 = _id;

    _id = target.name;

    Container.set(id1, _singleInstance || target);

    Container.setObj(_id, id1);

};};


// 数据存储类

// @libs/di/Container.ts

class Container {

    private ContainerMap = new Map<string | symbol, any>();

    private ContainerObjMap = new Map<string | symbol, any>();

    public set = (id: string | symbol, value: any): void => {

        this.ContainerMap.set(id, value);

    }

    public get = <T extends any>(id: string | symbol): T => {

        return this.ContainerMap.get(id) as T;

    }

    public has = (id: string | symbol): Boolean => {

        return this.ContainerMap.has(id);

    }

    public setObj = (id: string | symbol, value: any): void => {

        this.ContainerObjMap.set(id, value);

    }

    public getObj = <T extends any>(id: string | symbol): T => {

        return this.ContainerObjMap.get(id) as T;

    }

    public hasObj = (id: string | symbol): Boolean => {

        return this.ContainerObjMap.has(id);

    }

}

const ContainerInstance = new Container();

export default ContainerInstance;

我的目录

  • Data 默认配置数据文件
    • Data.ts 用来存储一些默认数据
  • Decorator 装饰器(就是上面的代码文件)
    • Container.ts
    • Inject.ts
    • Service.ts
  • Util 工具类 (自己需要什么加什么就好)
    • 音频管理
    • 存储管理(包含存档管理)
    • 时间管理
    • 配置管理
    • 日志管理
  • Language (多语言管理)
  • Framework (结构)
    • UIBase.ts (重要组件,所有组件的父节点)
    • LoadData.ts (重要组件,用来初始化项目,用来加载ui,弹窗,场景,音频,动画,创建与删除)
    • notifications.ts (重要组件,时间监听与派发)
  • View (ui页面,不重要,因人而异)
    • Popup 主逻辑页面,控制页面数据弹出窗口
    • Scene 场景
    • UI 绑定UI

这套框架很简单,方便书写代码。下面放出使用流程

使用流程

主要还是在UIBase 里面注册使用,理论上支持所有的ts文件,当前可以不太完整理论上注册完毕,都能实现

下面我已日志管理文件为例子

1.使用Service 文件注册我们的类


// @services/log.ts

import { Service } from './Service';

@Service(true)

export default class LogService {

    public debug(...args: any[]): void {

        console.debug('[DEB]', new Date(), ...args);

    }

    public info(...args: any[]): void {

        console.info('[INF]', new Date(), ...args);

    }

    public error(...args: any[]): void {

        console.error('[ERR]', new Date(), ...args);

    }

}

这是一个简单的日志实现,用来打印一些日志,现在下面我写一下,如何使用在其他页面使用这个文件

2.打开我们的UIBase文件,引入我们的注入器,只需要按照下面的写法,我们的日志类就引用好了


import LogServer from "../Decorator/LogService";

import { Inject } from "../Decorator/Inject";

export default class UIBase extends cc.Component {

       //日志基类

    @Inject(LogServer)

    logServer: LogServer;

}

3.在下面的功能类里面调用我们的UIBase父类,这样的话就可以使用我们的函数了


import UIBase from "../../Framework/UIBase";

const {ccclass, property} = cc._decorator;

@ccclass

export default class UIBag extends UIBase {

   

    onNode(){

        this.logServer.info("打印日志信息")

    }

}

我们只需要把我们需要的公有类引入到父类里面,就可以很方便的随时使用我们需要的函数

还可以使用Container 文件来查找我们注册好的类,防止我们二次New


Container.getObj('类名');

使用这套东西可能会方便一些功能开发,避免新建文件就来绑定一些公用类,使用UIbase 来统一管理。

后面可能会补充一些玩法,尽情期待吧,想要我自己使用的框架联系我吧

9赞

大家多多评论吧,我不知道好不好用

1赞

很好的思路,支持一下

感谢!可以试试,

互谢,好的!

也可以直接在LogServer文件导出单例吧(如果只是全局一份实例使用的话)
export var logServer = new LogServer()

1赞

这有其他用法,理论上这是一种方式,而且你这种每次都是新new

在使用IOC后,我们不必再浪费精力在管理实例的生命周期上,交给IOC代替我们管理,减少我们成吨的代码,

感觉并没有太大用处,相比于new反而还多了部分代码,复用对象直接new。单例就导出new,方便又快捷,ui则有专门的ui_manage管理

2赞

只会new一次

在使用IOC后,我们不必再浪费精力在管理实例的生命周期上,交给IOC代替我们管理,这套东西还是看场景,我上面写的只是一种方式。这之前是一套服务端的架构,容器管理,主要用于依赖控制。目前来看确实不太实用,唯一的好处只是他不用new和在各个文件中,可以取到new过的类。主要是我也一直在想可不可以用到ui 管理,可是ui 销毁

是的,只会一次

管理实例?管理了什么,只是存储一个对象?麻烦详细说明一下,是对象池不能用还是单例不能用?为什么多此一举?

兄弟别杠我,你去搜一下,依赖注入和loc

我只看了你的代码用例,只看出来了比 new 麻烦,如果你还要用户用你的东西之前再去看一堆资源,比如开发插件还需要学 vue,html ,css 谁愿意用?

这套东西之前用的元组,cocos不支持,只能退而求其次了

凭什么用我这套东西,我只是分享出来,你完绝对不好用你去杠springboot,你去杠阿里,这种使用方法都是他们提出来,我只是做了一套cocos版本的而已

先把自己产品的好处,解决了什么问题,怎么使用说明清楚,别人才知道,我从头看到尾只看到你说管理实例的生命周期,说的笼统又不举例,谁能明白?

无所谓了,我就是分享出来给大家看看。

这套代码,可能真不合适,cocos 我还在想具体用法。