白鷺引擎在2017年1月10日發布了 4.0 版本,將內部編譯器提升到了 TypeScript 2.1 。 本文的主要目標是向開發者介紹這為開發者帶來了哪些改變。
概述
在白鷺引擎 3.x 時代,引擎在執行構建命令時,使用的是內部定制的 TypeScript 1.8 編譯器,“內部定制” 主要包括:
- 添加生成類名稱注冊功能,以便白鷺引擎的反射 API
- 根據依賴關系,進行自動的文件排序功能
- 優化一些底層輸出邏輯,降低編譯體積
在白鷺引擎4.0版本,我們將編譯器版本從 TypeScript 1.8 提升到了 TypeScript 2.1,您可以從 TypeScript 官方文檔 了解從 TypeScript 1.8 至 2.1 引入的全新特性。除此之外,我向開發者簡單介紹一些常見的技巧和問題解決方式
新特性
允許使用 ECMAScript 6 的絕大部分新語法
您需要在tsconfig.json
中添加以下內容
{
"compilerOptions": {
"target": "es5",
"lib":[
"es5","dom","es6"
]
}
}
當您添加es6
字段后,就可以在白鷺引擎中使用全部 ES6 的新特性。ES6 功能列表您可以參見 ECMAScript 6 入門 這篇文章。
ECMAScript 6 的新特性中,屬于語法的部分會由 TypeScript 直接編譯為舊瀏覽器兼容的實現。屬于 API 的部分是需要開發者加入一個 polyfill 以保證舊瀏覽器不會報錯。目前引擎并沒有添加這些 polyfill,但是我們有計劃在 4.0.x 版本中為開發者自動添加 polyfill 支持。
更智能、更嚴格的 TypeScript 類型推斷
白鷺引擎4.0 版本中我們針對 TypeScript 的特性,將引擎 API 進行了更細致的梳理,引入更細致的 API 方法簽名,以比較常見的 DisplayObject.addEventListener
這個 API 為例,原來的方法簽名為
class DisplayObject {
public addEventListener(type:string,listener:Function,thisObject:any) {
}
}
class Main {
private run() {
var button = new DisplayObject();
button.addEventListener(egret.TouchEvent.TOUCH_TAP,
function(e:egret.TouchEvent) { // 事件類型必須手動聲明為 egret.TouchEvent,才能保證嚴格類型
this.doSomething(); // 第三個參數傳遞的是 button,函數里的 this 應該是button,不是 Main 的實例,所以不能調用 doSomething() 方法
},button);
);
}
private doSomething(){
}
}
比如在白鷺引擎4.0版本中,DisplayObject 的類型被調整為了以下類型
class DisplayObject {
public addEventListener<Z>(type:"tap",listener:(this:Z,e:egret.TouchEvent),thisObject:Z)
public addEventListener<Z>(type:string,listener:(this:Z,e:egret.Event),thisObject:Z) {
}
}
class Main {
private run() {
var button = new DisplayObject();
button.addEventListener(egret.TouchEvent.TOUCH_TAP,
function(e) { // 事件類型無需手動聲明就可保證嚴格類型
console.log (e.local_x) //由于已經推斷出 e 的類型是 egret.TouchEvent,所以這里會報錯
this.doSomething(); //自動推斷出這里的 this 應該是 button,進而檢查出這里會報錯
},button);
);
}
private doSomething(){
}
}
允許使用 async / await 關鍵詞
async / await 是 ES2017 語法標準,他可以大幅節省異步代碼的處理。注意使用這個語法糖需要在 tsconfig.json
中添加 lib : es6
或者 lib : es2015.promise
可能問題
升級到白鷺引擎4.0之后,您可能會遇到以下問題:
- Egret Wing 代碼提示報錯。
如果您遇到這種問題是因為您的 IDE 尚不支持 TypeScript 2.1,請把對應的 IDE 升級至最新版本。 Egret Wing 升級至 4.0 以上版本。 - 編譯代碼報錯
升級到 TypeScript 2.1 之后,TypeScript 變得更為智能,也變得更為嚴格,可能會有一些之前的不規范的寫法會導致報錯,對其進行調整即可,比如if ( x == false ) {
這樣的邏輯在 TypeScript 1.8 不會報錯,但是在 2.1 會報錯,因為這種代碼雖然是可以正確運行,但是有很大的潛在風險(比如 x = 0 )的時候。 - 編譯代碼出現錯誤,典型錯誤堆棧如下:
D:\GitHub\egret-core\tools\lib\typescript-plus\lib\typescript.js:57926
callExpression.arguments.forEach(function (argument) {
^
TypeError: Cannot read property 'forEach' of undefined
at visitCallExpression (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\t
ypescript.js:57926:33)
at visitExpression (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\types
cript.js:57824:17)
at visitStaticMember (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\typ
escript.js:57765:17)
at visitStatement (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\typesc
ript.js:57616:17)
at visitFile (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\typescript.
js:57602:13)
at buildDependencyMap (D:\GitHub\egret-core\tools\lib\typescript-plus\lib\ty
pescript.js:57590:13)
at Object.reorderSourceFiles (D:\GitHub\egret-core\tools\lib\typescript-plus
\lib\typescript.js:57562:9)
at Compiler.sortFiles (D:\GitHub\egret-core\tools\actions\Compiler.js:113:29
)
at Compiler.compileNew (D:\GitHub\egret-core\tools\actions\Compiler.js:101:1
4)
at Compiler.compileGame (D:\GitHub\egret-core\tools\actions\Compiler.js:52:2
5)
這個問題是我們在進行版本升級時考慮不周引發的問題,對此非常抱歉,這個問題已經在下一個版本( 4.0.1 ) 確認會得到解決,您也可以通過盡可能的不要在類的靜態屬性中直接創建對象來規避這個問題。