上一篇文章http://blog.youkuaiyun.com/afei198409/article/details/51327163中说到"渲染多级时,子列表数据必须放在sub_items数组中,如 {txt:"item 1", sub_items:[{txt:"sub item 1"},...]}",这就限制了数据的格式,实际上使用时会感觉很不方便,因为每个客户端的数据格式都不一致.
如开发者A是为某一鞋店开发客户端的,它的数据格式可能是这样的:
//鞋子列表
[
{id:0, name:"品牌1", shoes:[{id:10001, name:"男装休闲鞋", price:30}, {id:10002, name:"女装休闲鞋", price:30}, ...]},
{id:1, name:"品牌2", shoes:[{id:20001, name:"男装运动鞋", price:60}, {id:20002, name:"女装运动鞋", price:60}, ...]},
......
]
如上所见,shoes实际上就是一个子列表,如果要使用上文的多层级列表则就要重新构造数据,将它变成以下格式:
//新的鞋子列表
[
{id:0, name:"品牌1", sub_items:[{id:10001, name:"男装休闲鞋", price:30}, {id:10002, name:"女装休闲鞋", price:30}, ...]},
{id:1, name:"品牌2", sub_items:[{id:20001, name:"男装运动鞋", price:60}, {id:20002, name:"女装运动鞋", price:60}, ...]},
......
]
这的确令人尴尬.
下面主要针对这个问题作改进:
var CommonList = cc.Node.extend({
...
sub_items : "sub_items", // 1.添加一个变量,该变量是一个string,用于指向子列表
...
enableSubItem : function(tag, item_field) { // 2.在启用多层级的同时也修改子列表的指向
this.enable_sub_item = tag;
if(typeof (item_field) == 'string') {
this.sub_items = item_field;
}
},
...
// 3.在所有访问子列表数据的地方进行相应的替换,如下:dataSet[i].sub_items替换成dataSet[i][this.sub_items]
getItemData : function(dataSet) {
if(!dataSet || dataSet.length === 0) {
return;
}
for(var i = 0, len = dataSet.length; i < len; ++i) {
this._itemData.push(dataSet[i]);
if(this.enable_sub_item && dataSet[i]._itemOpen && dataSet[i][this.sub_items]) { // <--这里
this.getItemData(dataSet[i][this.sub_items]); // <--这里
}
}
},
...
resetData : function(dataSet, itemType, itemParent) {
if(!dataSet || dataSet.length === 0) {
return;
}
for(var i = 0, len = dataSet.length; i < len; ++i) {
dataSet[i]._itemLevel = itemType; //层级(从0开始计算)
dataSet[i]._itemOpen = false; //展开标记
dataSet[i]._itemIndex = i; //当前层级下的索引(从0开始计算)
dataSet[i]._itemCnt = dataSet.length; //当前层级总计算
dataSet[i]._itemParent = itemParent; //当前层级父节点
if(this.enable_sub_item && dataSet[i][this.sub_items]) { // <--这里
this.resetData(dataSet[i][this.sub_items], itemType + 1, dataSet[i]); // <--这里
}
}
},
...
closeItem: function (data) {
data._itemOpen = false;
if(data[this.sub_items] && 0 < data[this.sub_items].length) { // <--这里
for(var ind = 0; ind < data[this.sub_items].length; ++ind) { // <--这里
this.closeItem(data[this.sub_items][ind]); // <--这里
}
}
},
...
tableCellTouched:function (table, cell) {
...
if(this.enable_sub_item) {
if(data[this.sub_items] && 0 < data[this.sub_items].length) { // <--这里
data._itemOpen = data._itemOpen ? false : true;
reload = true;
//收缩其所有子项
if(!data._itemOpen) {
this.closeItem(data);
}
}else {
data._itemOpen = false;
}
}
...
},
...
});
现在我们重新使用CommonList来对鞋店列表进行渲染:
var common_list = new CommonList(l_size);
common_list.addItemPrefab(res.UIItemPrefab_1, 551, 60);
common_list.addItemPrefab(res.UIItemPrefab_2, 551, 63);
var list_delegate = {};
list_delegate.setItem = function (node, data) {
...
};
list_delegate.onItemClick = function (node, data) {
...
};
common_list.setDelegate(list_delegate);
var list_dataSet = [
{id:0, name:"品牌1", shoes:[{id:10001, name:"男装休闲鞋", price:30}, {id:10002, name:"女装休闲鞋", price:30}, ...]},
{id:1, name:"品牌2", shoes:[{id:20001, name:"男装运动鞋", price:60}, {id:20002, name:"女装运动鞋", price:60}, ...]},
......
];
common_list.enableSubItem(true, "shoes"); //启用多层级并修改子列表数据指向,让它指向shoes
common_list.reloadData(list_dataSet);
至此,数据结构限制就解除了.
不知你有没有注意到,上面改进时也另添加了另一项数据改进:
resetData : function(dataSet, itemType, itemParent) {
...
for(var i = 0, len = dataSet.length; i < len; ++i) {
...
dataSet[i]._itemParent = itemParent; //当前层级父节点
...
}
},
_itemParent记录父节点数据.它有何用处呢?
如当点击列表"男装休闲鞋"这一项时,会触发回调:
list_delegate.onItemClick = function (node, data) {
...
};
这时这里参数data指向{id:10001, name:"男装休闲鞋", price:30},这个时候如果开发者想得到这一子项的父节点数据,如id,name,直接访问data._itemParent即可得到:
data._itemParent.id //值为 0
data._itemParent.name //值为 "品牌1"