參考
LayaAir 下如何使用加載模式
LayaAir下分離模式的使用
2.0引擎的四種發(fā)布模式的區(qū)別
Laya2.0 內(nèi)嵌模式、加載模式、分離模式、文件模式的場(chǎng)景加載創(chuàng)建和場(chǎng)景打開(kāi)關(guān)閉

一、差異
內(nèi)嵌模式:內(nèi)嵌模式會(huì)把編輯器的UI內(nèi)容生成一個(gè)場(chǎng)景類代碼文件,代碼腳本里包含IDE創(chuàng)建的UI場(chǎng)景的信息,在小游戲和輕游戲還沒(méi)有問(wèn)世的時(shí)候,不用考慮js 的大小,正常開(kāi)發(fā)h5最常用的選擇,而且不涉及異步加載打開(kāi)頁(yè)面速度也最快。
加載模式: 加載模式也會(huì)生成場(chǎng)景類,其他的UI數(shù)據(jù)信息會(huì)放到一個(gè)ui.json內(nèi),使用時(shí)需要加載這個(gè)json,同樣在沒(méi)有小游戲的時(shí)代不常用,場(chǎng)景信息可以不在js中,可以節(jié)省js包體大小,給小游戲4m包節(jié)省更多空間。使用時(shí)可以作為資源加載。
分離模式: 分離模式是在加載模式基礎(chǔ)上,同樣也會(huì)生成場(chǎng)景類,但他會(huì)把每個(gè)場(chǎng)景生成單獨(dú)的場(chǎng)景數(shù)據(jù)文件,每次單獨(dú)加載場(chǎng)景文件,區(qū)別于加載模式一次把所有場(chǎng)景都加載。在2.0以后,開(kāi)發(fā)小游戲或輕游戲,為了減少主包大小和提升加載速度都是常用的模式。
文件模式(Laya2.0默認(rèn)為文件模式):文件模式是2.0特有的,為了開(kāi)發(fā)小游戲而創(chuàng)建的,他不生成場(chǎng)景類,也就是能進(jìn)一步減少js包的大小,使用的時(shí)候用Scene.load方式加載,區(qū)別于前三種最大的的不同就是,文件模式不能直接調(diào)用場(chǎng)景內(nèi)的變量,需要getchild獲取之后進(jìn)行操作。前三種的場(chǎng)景類里聲明了變量,有代碼提示直接可以操作內(nèi)部的變量。
需要注意的是,在選擇js 語(yǔ)言開(kāi)發(fā)時(shí), 分離模式和文件模式是沒(méi)有區(qū)別的,都沒(méi)有場(chǎng)景類。
內(nèi)嵌模式
import View=laya.ui.View;
import Dialog=laya.ui.Dialog;
module ui {
export class APageUI extends View {
public static uiView:any ={"type":"View","props":{"width":150,"height":31},
"child":[{"type":"Image","props":{"y":2,"x":22,"skin":"comp/bg.png"}}]};
constructor(){ super()}
createChildren():void {
super.createChildren();
this.createView(ui.APageUI.uiView);
}
}
}
加載模式和分離模式
import View=laya.ui.View;
import Dialog=laya.ui.Dialog;
module ui {
export class APageUI extends View {
constructor(){ super()}
createChildren():void {
super.createChildren();
this.loadUI("APage");
}
}
}
對(duì)比一下,在內(nèi)嵌模式下,uiView那些JSON都在layaUI里,可以直接調(diào)用createView傳進(jìn)去。而在分離模式和加載模式下,則被分離出去了。
加載模式:


分離模式:


看一下源碼就知道使用方式了
//在View.as中
/**存儲(chǔ)UI配置數(shù)據(jù)(用于加載模式)。*/
public static var uiMap:Object = {};
/**
* @private
* 裝載UI視圖。用于加載模式。
* @param path UI資源地址。
*/
protected function loadUI(path:String):void {
var uiView:Object = uiMap[path];
uiView && createView(uiView);
}
加載模式和分離模式
import View=laya.ui.View;
import Dialog=laya.ui.Dialog;
module ui {
export class APageUI extends View {
constructor(){ super()}
createChildren():void {
super.createChildren();
this.loadUI("APage");
}
}
}
這里也能看到加載模式和分離模式的區(qū)別所在:如果uiMap里有JSON數(shù)據(jù),則在createChildren時(shí)就調(diào)用了createView,達(dá)到了與內(nèi)嵌模式一致的效果。而uiMap里如果沒(méi)有JSON數(shù)據(jù),則需要自己調(diào)用了。
看一下加載模式的寫(xiě)法:
// 程序入口
Laya.init(600, 400);
Laya.loader.load([{ url: "res/atlas/comp.json", type: Loader.ATLAS },
{ url: "res/ui.json", type: Loader.JSON }], Handler.create(this, this.onLoaded));
function onLoaded(): void {
View.uiMap = Laya.loader.getRes("test/ui.json");
//實(shí)例UI界面
var testUI: TestUI = new TestUI();
Laya.stage.addChild(testUI);
}
注意View.uiMap = Laya.loader.getRes("test/ui.json");
分離模式則不需要處理View.uiMap,而是在自己的單獨(dú)頁(yè)面里用createView調(diào)用自己的json文件
class TestUI extends ui.test.TestPageUI {
createChildren():void {
this.createView(Laya.loader.getRes("test/TestPage.json"));
super.createChildren();
}
如果希望這個(gè)調(diào)用json的操作,能在IDE中自動(dòng)處理,可以參考編輯器選擇分離模式生成TS代碼時(shí)能自動(dòng)在createChildren里加上createView調(diào)用代碼么?
自行修改LayaAirIDE生成ui代碼所調(diào)用的腳本,文件名是LayaAirCmdTool.max.js.打開(kāi)這個(gè)js之后讀一下行號(hào)為21205:CodeManager.createByDir這個(gè)函數(shù)。。這個(gè)函數(shù)是導(dǎo)出ui代碼的,重點(diǎn)看一下21281這一行
code=CodeManager.objToUI(obj,tFile);好的,跳轉(zhuǎn)到這個(gè)objToUI的函數(shù)定義的地方:21425行,是這個(gè)函數(shù)的開(kāi)始位置,函數(shù)不長(zhǎng),我相信你有一百種方法,在字符串中塞入自己想要的內(nèi)容呢。
二、Laya1.0項(xiàng)目使用效果
以實(shí)際項(xiàng)目為例,在index.html中有<script src="js/ui/layaUI.max.all.js"></script>,如果是內(nèi)嵌模式,這個(gè)js文件有506K。如果使用分離模式,這個(gè)JS文件就變成78K,而分離出來(lái)的UI文件夾則是364K。如果是加載模式,ui.json是368K大小,和分離模式差不太多。很顯然,layaUI.max.all.js這個(gè)文件變小,會(huì)讓index.html加載速度變快很多。
index.html需要加載的目前有幾大部分:
NotoSans-Bold.woff 25k
core.min.js 276k
webgl.min.js 157k
filter.min.js 5k
html.min.js 18k
ui.min.js 107k
Laya引擎庫(kù)合計(jì)563k
第三方庫(kù):
externalLib.min.js 414k
gameLib.min.js 98k
player.min.js 801k
js/ui/layaUI.max.all.js 506k 可以使用分離模式變成78k(分離出來(lái)的json是368k)
純js的加載頁(yè)面,太復(fù)雜的效果不好控制,并且引入laya引擎后還要移除。好處是能節(jié)省laya引擎庫(kù)的563k。目前考慮用laya做一個(gè)首次加載頁(yè)面,先把自己用的資源加載顯示,再把第三方庫(kù)、項(xiàng)目其它資源加載進(jìn)來(lái)。這樣在發(fā)布時(shí),用IDE自帶的壓縮合并JS選項(xiàng)就不適用了,需要把首次加載頁(yè)面用到的JS使用分離模式單獨(dú)打包成一個(gè)JS文件,把剩余的JS打包成另外的JS文件。這個(gè)可以用GULP腳本來(lái)做,通過(guò)讀取index.html標(biāo)簽中引用的JS來(lái)進(jìn)行分離。
三、Laya2.0項(xiàng)目
1.加載模式
內(nèi)嵌模式加載太慢不說(shuō)了,這里以上面Laya1.0的加載模式為思路做了測(cè)試,發(fā)現(xiàn)挺麻煩的。
import {ui} from "./ui/layaMaxUI";
.......
onConfigLoaded(): void {
//加載IDE指定的場(chǎng)景
Laya.loader.load('ui.json',Laya.Handler.create(this, this.gameStart));
}
gameStart():void{
Laya.View.uiMap = Laya.Loader.getRes('ui.json');
var sc = new ui.Hello2UI();
Laya.stage.addChild(sc);
受laya2.0影響,文件開(kāi)頭要先import那個(gè)UI文件,但是運(yùn)行發(fā)現(xiàn)報(bào)錯(cuò),找不到Hello.json。奇怪啊,明明用的加載模式,怎么還像分離模式一樣去找那個(gè)單獨(dú)的json呢。
原來(lái)layaMaxUI.ts是這樣寫(xiě)的:
export class Hello2UI extends Scene {
constructor(){ super()}
createChildren():void {
super.createChildren();
this.loadScene("Hello2");
}
}
對(duì)照一下Scene的源碼:
/**
* @private 兼容老項(xiàng)目
* 裝載場(chǎng)景視圖。用于加載模式。
* @param path 場(chǎng)景地址。
*/
public function loadScene(path:String):void {
var url:String = path.indexOf(".") > -1 ? path : path + ".scene";
var view:Object = Laya.loader.getRes(url);
if (view) {
createView(view);
} else {
Laya.loader.load(url, Handler.create(this, createView), null, Loader.JSON);
}
}
這里注釋里寫(xiě)著兼容老項(xiàng)目的加載模式,可是createView傳入的那個(gè)view取值方式不對(duì),應(yīng)該是Laya.View.uiMap[url],這應(yīng)該是引擎BUG,估計(jì)以后會(huì)修復(fù)。暫時(shí)可以自己創(chuàng)建一個(gè)scene:
export default class Hello2Scene extends Laya.Scene {
constructor() {
super();
this.createView(Laya.View.uiMap['Hello2']);
}
}
2.分離模式
分離模式會(huì)生成單獨(dú)的json,所以像上面loadScene找不到單獨(dú)json文件的引擎BUG就不會(huì)出現(xiàn)了。但是寫(xiě)法仍然是差不多的,只是不用再設(shè)置Laya.View.uiMap = Laya.Loader.getRes('ui.json');而已。
//layaMaxUI.ts
export module ui {
export class Hello1UI extends Scene {
public tesImg:Laya.Image;
constructor(){ super()}
createChildren():void {
super.createChildren();
this.loadScene("Hello1");
}
}
}
//Hello1Scene.ts
import { ui } from "./ui/layaMaxUI";
export default class Hello1Scene extends ui.Hello1UI {
createChildren():void {
super.createChildren();
console.log('this.testImg',this.tesImg);
this.on('onViewCreated',this,this.onViewCreatedHandler);
}
onViewCreatedHandler():void{
console.log("this.testImg:", this.tesImg);
}
}
//Main.ts
onConfigLoaded(): void {
//加載IDE指定的場(chǎng)景
//GameConfig.startScene && Laya.Scene.open(GameConfig.startScene);
var sc = new Hello1Scene();
Laya.stage.addChild(sc);
}
這里從測(cè)試代碼里可以看出,createChildren里居然訪問(wèn)不到頁(yè)面的變量this.testImg,這在laya1.0里是可以正常訪問(wèn)的。只能參考引擎的Scene代碼,在onViewCreated事件里,才能訪問(wèn)到。
scene.on("onViewCreated", null, function():void {
complete && complete.runWith(scene)
})
scene.createView(obj);
所以,上面的這種寫(xiě)法、思維方式,還是laya1.0時(shí)代仿flash時(shí)代的套路,是時(shí)候改變一下了,laya2.0的組件化封裝場(chǎng)景Scene、runtime、prefab