LayaAir IDE版本和庫版本: 1.8.0
Laya的ui控件list的渲染有兩種常見的實(shí)現(xiàn)方式。
- 通過
itemRender實(shí)現(xiàn):- 給
list.itemRender賦值一個(gè)實(shí)現(xiàn)了dataSource接口的類定義; - 通過
list.array傳入數(shù)據(jù)源;
- 給
- 通過
renderHandler實(shí)現(xiàn):- 在
LayaAir IDE的編輯模式下給List控件添加Box控件作為其子級(jí)容器; - 將該
Box控件的renderType屬性設(shè)置為render; - 給
list.renderHandler賦值一個(gè)Handler對(duì)象; - 通過
list.array傳入數(shù)據(jù)源;
- 在
不過本文只探討使用第2種實(shí)現(xiàn)方式需要注意的地方。
通過renderHandler實(shí)現(xiàn)渲染時(shí),box與dataSource遵循“有則賦值”規(guī)則
什么是“有則賦值”?說人話就是,通過dataSource傳入的數(shù)據(jù)對(duì)象與box存在共有的屬性(名字相同的屬性)時(shí),將會(huì)把數(shù)據(jù)對(duì)象的值賦給box。邏輯類似于:
if(data.hasOwnProperty('name') && box.hasOwnProperty('name')){
box.name = data.name;
}
下面通過一個(gè)例子來說明,以下是一個(gè)將動(dòng)物信息展示出來的list實(shí)現(xiàn):
import WebGL = Laya.WebGL;
// 程序入口
class GameMain{
constructor()
{
Laya.init(400,600, WebGL);
Laya.stage.bgColor = '#FFFFFF';
Laya.loader.load('res/atlas/comp.atlas', Laya.Handler.create(this, ()=>{
const data:{name:string, weight:number, src:string}[] = [];
data.push({name:'小狗', weight:5, src:'dog.png'});
data.push({name:'小貓', weight:3, src:'cat.png'});
data.push({name:'小鳥', weight:0.2, src:'bird.png'});
data.push({name:'小雞', weight:0.5, src:'chick.png'});
data.push({name:'小豬', weight:10, src:'pig.png'});
const view:ui.ListViewUI = new ui.ListViewUI();
view.pos(50,50);
view.listDemo.array = data;
Laya.stage.addChild(view);
view.listDemo.renderHandler = Laya.Handler.create(this, (itemRender:Laya.Box, index:number)=>{
const label:Laya.Label = itemRender.getChildByName('lblContent') as Laya.Label;
const d = data[index];
label.changeText(d.name + ' 重量:' + d.weight + ' 圖像:' + d.src);
}, undefined, false);
}))
}
}
new GameMain();
運(yùn)行效果如下圖:

目前表現(xiàn)跟預(yù)期還是一致的,接下來,假設(shè)每種動(dòng)物的圖片資源尺寸不一,并且怪物形象在圖片中的實(shí)際位置也不統(tǒng)一。我們需要增加pivotX和pivotY的配置,來統(tǒng)一怪物形象的實(shí)際顯示位置。我們對(duì)以上代碼做如下的修改:
import WebGL = Laya.WebGL;
// 程序入口
class GameMain{
constructor()
{
Laya.init(400,600, WebGL);
Laya.stage.bgColor = '#FFFFFF';
Laya.loader.load('res/atlas/comp.atlas', Laya.Handler.create(this, ()=>{
// 僅對(duì)數(shù)據(jù)源做了修改,增加了pivotX和pivotY屬性
const data:{name:string, weight:number, src:string, pivotX:number, pivotY:number}[] = [];
data.push({name:'小狗', weight:5, src:'dog.png', pivotX:0, pivotY:0});
data.push({name:'小貓', weight:3, src:'cat.png', pivotX:20, pivotY:0});
data.push({name:'小鳥', weight:0.2, src:'bird.png', pivotX:0, pivotY:0});
data.push({name:'小雞', weight:0.5, src:'chick.png', pivotX:-20, pivotY:0});
data.push({name:'小豬', weight:10, src:'pig.png', pivotX:0, pivotY:0});
view.pos(50,50);
view.listDemo.array = data;
Laya.stage.addChild(view);
view.listDemo.renderHandler = Laya.Handler.create(this, (itemRender:Laya.Box, index:number)=>{
const label:Laya.Label = itemRender.getChildByName('lblContent') as Laya.Label;
const d = data[index];
label.changeText(d.name + ' 重量:' + d.weight + ' 圖像:' + d.src);
}, undefined, false);
}))
}
}
new GameMain();
運(yùn)行效果如下圖:

我的天!剛才一切正常的表現(xiàn),居然發(fā)生了異常,list的渲染出來的item錯(cuò)位了。其實(shí)這里就是上文說的“有則賦值”的規(guī)則,我們實(shí)際并沒有預(yù)期要把dataSource的pivotX和pivotY賦值給box,但實(shí)際卻發(fā)生了。
我們可以把數(shù)據(jù)源里的pivotX和pivotY修改為srcPivotX和srcPivotY來避免上述意外的發(fā)生,我真是個(gè)小機(jī)靈鬼。(也可以通過其他方式避免,本文不贅述)
data.push({name:'小狗', weight:5, src:'dog.png', srcPivotX:0, srcPivotY:0});
總結(jié):通過renderHandler實(shí)現(xiàn)list渲染的時(shí)候,千萬要注意共有屬性的非預(yù)期賦值。
引申:發(fā)生上述“有則賦值”的地方在Laya的Box控件,其有一接口為dataSource來接收數(shù)據(jù)源,可以在laya.ui.js找到以下代碼,有興趣的同學(xué)可以斷點(diǎn)調(diào)試加深了解,這里也不詳述了:
/**
*<code>Box</code> 類是一個(gè)控件容器類。
*/
//class laya.ui.Box extends laya.ui.Component
var Box=(function(_super){
function Box(){
Box.__super.call(this);;
}
__class(Box,'laya.ui.Box',_super);
var __proto=Box.prototype;
Laya.imps(__proto,{"laya.ui.IBox":true})
/**@inheritDoc */
__getset(0,__proto,'dataSource',_super.prototype._$get_dataSource,function(value){
this._dataSource=value;
for (var name in value){
var comp=this.getChildByName(name);
if (comp)comp.dataSource=value[name];
else if (this.hasOwnProperty(name)&& !((typeof (this[name])=='function')))this[name]=value[name];
}
});
return Box;
})(Component)