easyui显示编辑树形资料有TreeGrid元件,但是这个元件的vue版本和react版本没有分页功能。virtual scroll功能也表现不佳。
我用DataGrid来处理。要解决的问题点:
(1)如何显示成树形。即,子节点如何有缩进。
先计算好每个节点的层级level,然后template中设置缩进大小。
<template v-slot:body="{row,column,rowIndex}">
<div v-Droppable="{dragEnter:onDDKeyDragEnter,drop:onDDKeyDrop}"
v-Draggable="{row:row,proxy:$refs.DDKeyDragProxy,revert:true,axis:'v',dragStart:onDDKeyDragStart,dragEnd:onDDKeyDragEnd,drag:onDDKeyDrag}"
@click="onDDKeyClick">
<span class='tree-indent' :style='{width:(row.acroStates.level*16).toString()+"px"}'></span>
<span v-if="row.children && row.children.length>0" :class="getDDKeyExpanderClass(row)" @click="onRowToggle($event,row)"></span>
<span v-else class='tree-indent'></span>
<span class='tree-title'>{{row[column.field]}}</span>
</div>
</template>
(2)如何展开和收拢节点。
展开收拢时,计算好每个节点的isVisual属性,通过DataGrid的filter来显示和隐藏。
expandRowRules:[{
field:'isVisual',
op:'equal',
value:true
}],
......
<DataGrid :filterRules="expandRowRules">
......
toggleRow(row){
if (row.acroStates.state=='open') row.acroStates.state='closed';
else row.acroStates.state='open';
let root=row;
function scanNodes(parent,children){
for(let i=0;i<children.length;i++){
let node=children[i];
node.isVisual=root.acroStates.state=='open' && parent.acroStates.state=='open';
if (node.children) scanNodes(node,node.children);
}
}
if (row.children) scanNodes(row,row.children);
},
......
onRowToggle(e,row){
//console.log('toggle',e,row);
//this.finishEditing();
util_treePlain.toggleRow(row);
this.$refs.tree.doFilter();
//取消冒泡,使其不触发cellclick事件
e.cancelBubble=true;
e.preventDefault();
e.stopPropagation();
},
(3)排序时如何保持节点的上下级层级关系。
节点按同级排序,按深度优先扫描树形节点,把节点一个个加入到平面的数组中。
expandTree2Plain(treeRows){
let rows=[];
function scanNodes(nodes,level){
for(let i=0;i<nodes.length;i++){
let node=nodes[i];
if (!node.acroStates){
node.acroStates={
state:'open'
}
}
node.acroStates.level=level;
node.acroStates.index=rows.length;
node.isVisual=node.acroStates.state=='open';
rows.push(node);
if (node.children){
scanNodes(node.children,level+1);
}
}
}
scanNodes(treeRows,0);
return rows;
},
sortTree2Plain(treeRows,sorts){
let rows=[];
function scanNodes(nodes){
if (sorts && sorts.length>0){
nodes.sort(function(a,b){
let r;
let v1=a[sorts[0].field];
let v2=b[sorts[0].field];
if (v1==null||v1==undefined) v1='';
if (v2==null||v2==undefined) v2='';
if (sorts[0].field=='SortNumber'){
if (v1=='') v1=-1;else v1=parseInt(v1);
if (v2=='') v2=-1;v2=parseInt(v2);
}
if (v1<v2) r=-1;
else if (v1==v2) r=0;
else r=1;
if (sorts[0].order=='desc') r=-r;
return r;
});
}
for(let i=0;i<nodes.length;i++){
let node=nodes[i];
node.acroStates.index=rows.length;
rows.push(node);
if (node.children) scanNodes(node.children);
}
}
scanNodes(treeRows);
//console.log(rows);
return rows;
},