TypeScript对于习惯强类型语言(比如Unity C#)而又要写JavaScript项目(比如CocosCreator Egret)的程序员来说,确实提供了很大方便,而且对于一些由于弱类型语言导致的只能运行时检查的低级错误,使用TS都能很好的避免。
这次要记录的是使用TypeScript作为主开发语言的CocosCreator项目中引用第三方库的方法和问题,实测的是MessagePack,protobufjs和Photon这几个库。
首先是MessagePack,这个用了最无脑的npm包方式,虽然新版本的Creator(我写这篇博文的时候用的是v2.1.0)已经号称不支持npm方式引用第三方库(据说从1.6开始,http://forum.cocos.com/t/1-6-npm/49926),但实测直接以node npm方式在项目根目录下添加package.json并指定第三方库还是可以正常工作的,当然如论坛里官方人员说的,这样确实会带来某些弊端,比如依赖之类的,但毫无疑问npm管理第三方js库是最方便的。对于MsgPack,package.json可以直接手写如下:
{
"name": "",
"version": "",
"dependencies": {
"@types/msgpack-lite": "^0.1.6",
"msgpack-lite": "^0.1.26"
}
}
也可以npm install -S方式,这样完成后还会直接安装ts需要的.d接口定义,直接在Creator .ts里使用即可:
import * as msgpack from "msgpack-lite";
const { ccclass, property } = cc._decorator;
@ccclass
export default class Helloworld extends cc.Component {
@property(cc.Label)
label: cc.Label = null;
@property
text: string = 'hello';
start() {
// init logic
this.label.string = this.text;
const temp = msgpack.encode({ test: "asdasd" });
console.log(">>>>", temp);
const dtemp = msgpack.decode(temp);
console.log("<<<<<", dtemp);
}
}
下一个是Photon JS库,这个就没有npm包方式了,只有官网提供的Download SDK方式下载:https://www.photonengine.com/en-us/sdks#realtimejavascript,这个就要按照Creator目前官方推荐的方式引入了:https://docs.cocos.com/creator/manual/zh/scripting/plugin-scripts.html,由于不需要调试或读js源码,接口有ts定义,所以直接复制下载好的Photon JS库中的Photon-Javascript_SDK.min.js和Photon-Javascript_SDK.d.ts到Creator项目中,并且标记插件脚本即可:
由于这种方式,Creator会将插件脚本进行全局化处理,因此不用像MsgPack那样再做import,直接使用即可(实测VSCode这样基于ts定义的感知也可正常工作):
this._photonLBC = new Photon.LoadBalancing.LoadBalancingClient(
Photon.ConnectionProtocol.Ws,
appId,
ConstData.CLIENT_VER
);
this._photonLBC.onStateChange = (state: number) => {
cc.log("LBC onStateChange: " + state);
const sceneMain = cc.find("Canvas").getComponent(SceneMain);
const LBCState = Photon.LoadBalancing.LoadBalancingClient.State;
switch (state) {
case LBCState.ConnectedToNameServer:
sceneMain.outputLog("已连接NameServer!");
break;
case LBCState.ConnectedToMaster:
sceneMain.outputLog("已连接Master!");
break;
case LBCState.JoinedLobby:
sceneMain.outputLog("已加入Lobby!");
break;
case LBCState.Joined:
break;
case LBCState.Disconnected:
sceneMain.outputLog("已断开连接!");
break;
default:
cc.warn(`LBC state not handled: ${state}`);
break;
}
};
最后是Protobuf,这个在之前的js项目中也用到过了,而且百度下相关资料一大把,各种引入方式,各种使用方式,proto生成js文件的,直接使用proto动态解析的,并且刚才给出的官方文档里,也以protobufjs为例进行了说明:
如果插件还依赖于其它插件,也需要把多个插件合并为单个 js 文件
以 protobuf.js 为例,这个库还依赖于 bytebuffer.js,但是插件作者并没有提供整合好的独立运行版本。我们可以先下载到这两个库各自编译后的两个文件 protobuf.js 和 bytebuffer.js,然后使用文本编辑器或类似cat
这样的命令行工具将这两个脚本拼合成一个新的脚本 protobuf_all.js。然后就能在 Creator 中直接使用这个 protobuf_all.js 了。
现在新release的6.x已经不需要再手动做这个整合操作了,直接将pbjs作者提供好的protobuf.min.js和index.d.ts改名为protobuf.d.ts一起复制进项目,然后如法炮制设置插件脚本,这样都设置好以后,会发现并没有像刚才Photon那样开箱即用,而会收到这么个错误:
‘protobuf’ refers to a UMD global, but the current file is a module. Consider adding an import instead.ts(2686)
一通查之后,发现问题在于protobuf.d.ts中的namespace声明方式,其实直接无视这个lint错误,在编译到js状态时运行还是不会出错的,但这样一来代码里一直有错误提示,二来ts的大优势,代码感知protobuf相关的就用不了了,所以解决方法是修改下.d.ts,在最外层像Photon库一样使用declare module方式声明:
// export as namespace protobuf;
declare module protobuf {
/**
* Provides common type definitions.
* Can also be used to provide additional google types or your own custom types.
* @param name Short name as in `google/protobuf/[name].proto` or full file name
* @param json JSON definition within `google.protobuf` if a short name, otherwise the file's root definition
*/
export function common(name: string, json: { [k: string]: any }): void;
export namespace common {
/** Properties of a google.protobuf.Any message. */
interface IAny {
typeUrl?: string;
bytes?: Uint8Array;
}
...
/**
* An allocator as used by {@link util.pool}.
* @param size Buffer size
* @returns Buffer
*/
type PoolAllocator = (size: number) => Uint8Array;
/**
* A slicer as used by {@link util.pool}.
* @param start Start offset
* @param end End offset
* @returns Buffer slice
*/
type PoolSlicer = (this: Uint8Array, start: number, end: number) => Uint8Array;
}
这样修改以后,ts使用时就不会报错了,也可以正常感知protobufjs相关api了。
博主友情提示:
如您在评论中需要提及如QQ号、电子邮件地址或其他隐私敏感信息,欢迎使用>>博主专用加密工具v3<<处理后发布,原文只有博主可以看到。