问题:

 

编译之后,继承与component的类,可以通过cc.js.getClassName获取类名,但是自定义类的类名是没法获取的

分析:

1.查看源码,能通过cc.js.getClassName调用函数名,必须要经过js.setClassName 函数定义;

//文件地址:engine/cocos2d/platform/js.js

  /**
     * Register the class by specified name manually
     * @method setClassName
     * @param {String} className
     * @param {Function} constructor
     */
    js.setClassName = function (className, constructor) {
        doSetClassName(className, constructor);
        // auto set class id
        if (!constructor.prototype.hasOwnProperty('__cid__')) {
            var id = className || tempCIDGenerater.getNewId();
            if (id) {
                js._setClassId(id, constructor);
            }
        }
    };

2.查找setClassName的使用

//文件地址:engine/cocos2d/core/platform




function CCClass (options) {
    options = options || {};

    var name = options.name;
    var base = options.extends/* || CCObject*/;
    var mixins = options.mixins;

    // create constructor
    var cls = define(name, base, mixins, options);
    if (!name) {
        name = cc.js.getClassName(cls);
    }

    ...
}


function define (className, baseClass, mixins, options) {
    var Component = cc.Component;
    var frame = cc._RF.peek();
    if (frame && js.isChildClassOf(baseClass, Component)) {
       //发现只有继承Component的才会在这里赋值 frame.script
        className = className || frame.script;
    }

    var cls = doDefine(className, baseClass, mixins, options);

    if (frame) {
        ...
    }
    return cls;
}



function doDefine (className, baseClass, mixins, options) {
    ...
    js.setClassName(className, fireClass);
    return fireClass;
}

3.发现所有的ccclass 都会经过如上代码,

在define函数中,只有继承Component才会去 用frame.script赋值给className,

我们看看frame.script的来历

cc._RF = {
    push: function (module, uuid, script) {
        if (script === undefined) {
            script = uuid;
            uuid = '';
        }
        requiringFrames.push({
            uuid: uuid,
            script: script,
            module: module,
            exports: module.exports,    // original exports
            beh: null
        });
    },
    pop: function () {
        var frameInfo = requiringFrames.pop();
        // check exports
        var module = frameInfo.module;
        var exports = module.exports;
        if (exports === frameInfo.exports) {
            for (var anyKey in exports) {
                // exported
                return;
            }
            // auto export component
            module.exports = exports = frameInfo.cls;
        }
    },
    peek: function () {
        return requiringFrames[requiringFrames.length - 1];
    }
};

上面是HelloWorld编译后的代码

我们可以发现,cc._RF先 push 进去了一个对象,然后再调用@class装饰器生成类,

再生成类的过程中会调用上面的  define 函数, 然后用 cc._RF.peek() 查看存入的对象,从而拿到类名

解题思路:

用装饰器,在构造类的过程中去获取类名,调用 cc.js.setClassName() 设置类名

解决办法:

//创建类的装饰器,使用和ccclass类似

function keepClassName(target){
        let frameInfo = cc['_RF'].peek();
        let script = frameInfo.script;
        cc.js.setClassName(script, target);
}


//用法

@keepClassName
export class UserClass{


}

Logo

这里是一个专注于游戏开发的社区,我们致力于为广大游戏爱好者提供一个良好的学习和交流平台。我们的专区包含了各大流行引擎的技术博文,涵盖了从入门到进阶的各个阶段,无论你是初学者还是资深开发者,都能在这里找到适合自己的内容。除此之外,我们还会不定期举办游戏开发相关的活动,让大家更好地交流互动。加入我们,一起探索游戏开发的奥秘吧!

更多推荐