微信小游戏egret.getDefinitionByName不能获取类的实例

    技术2022-07-10  115

    前言:熟悉MVC框架的小伙伴都知道,在创建界面的时候一般使用egret.getDefinitionByName()来获取到类,从而可以实例化出一个界面类。

    今天遇到一个问题:在本地调试好的项目,上到微信开发者工具的时候,loading之后的第一个界面就没有正常显示,报错 viewClass is not a constructor 。因为是在第三方引擎开发的项目(Egret),所以在微信开发者工具的调试面板只能看到一堆min.js的内容,大概意思就是说界面的类因为没有明确声明 window['viewUI'] = viewUI所以js不能把这个类实例化。 但是我们的框架里的界面类都是通过名字字符获取到的呀,每一个都声明一下,那还要框架干嘛。针对这个问题,经过研究,我们可以修改一下微信打包的工具,在编译阶段动态的声明一下。下面记录一下这个过程:

    1、 报错的位置
    let viewClass = egret.getDefinitionByName(viewName); let view = new viewClass;

    error : viewClass is not a constructor

    2、我们查看 egret.getDefinitionByName()的定义:
    /** * 返回 name 参数指定的类的类对象引用。 * @param name 类的名称。 * @version Egret 2.4 * @platform Web,Native * @includeExample egret/utils/getDefinitionByName.ts * @language zh_CN */ function getDefinitionByName(name: string): any;

    这里可以看到,适用平台确实没有微信小游戏,(以前从没遇见过,不知道啥时候悄悄改的API ) 我们知道,使用TS开发,其实引擎底层都是给我们做过声明的,这样才能通过 TS的代码 调用到对应的类.prototype跑起来. 最次的办法,就是这样声明: window['HallViewUI'] = HallViewUI ,这样JS那边就不会报错。 但是,那么问题来了,我们的view Manager 是通过名字来获取具体的类的,如果要一个一个的声明,那么我干脆把MVC框架全删了, 省的这么折腾了。这种方法肯定不可行。

    3、分析,由于只有微信平台会遇到这个问题

    所以,我们可以改变微信的打包流程,在打包的时候做一个动态的声明。 打开微信打包的配置文件 ./script/wxgame/wxgame.ts 就是他了。 对于这个文件的内容我不再赘述。直接在onFile方法里,我们找到最后关于 main.js 的处理。 修改如下:

    if (filename == 'main.js') { content = content.replace(/(__reflect\((\w+)\.prototype, "(\w+)"\);)/g, "$1 window.$3=$3"); content += ";window.Main = Main;" }
    4、编译项目目录,编译,打包微信小游戏

    修改打包微信的各种配置和第三方的统计设置等等。这些一般我们都会写一个shell脚本来代替。再次跑在微信开发者工具上,发现,问题已经不存在了。搞定。

    5、分析总结

    我没有体验过直接在微信开发者工具上面从零开始开发一个游戏项目。因为我自身比较难以忍受弱类型的语言,比如js。还是强类型的语言用着才舒服。所以一直借用egret或者laya或者Cocos来开发小游戏项目。每一次上微信的时候,都会多多少少遇到一些问题。我总结了基本都是打包配置,微信公众平台配置,API兼容问题,适配问题。等等。遇到问题不可怕,重要 的是要滤清步骤和关系。一点一点的解决问题。所有的问题都是你变强大的阶梯。

    写这个主要是用来记录问题和解决方法,不停鞭策自己。当然也希望帮到有需要的兄弟。

    如果你也遇到这个问题,看完这篇文章帮你解决了问题。希望你帮我点个赞,嘻嘻,谢谢.

    Processed: 0.010, SQL: 9