前端使用ExtJS6,要求在菜单树上对菜单树的数据进行筛选,提高用户的体验。
现在功能已经完成,这里记录下来便于后面遇到类似问题作为参考,会贴上源码和官方Demo提供参考的源码。
对Tree的筛选,有两种情况 ,一种是Tree的DataSource已经加载完毕,和Tree进行了互相绑定,不在进行改变。这种情况的效果如下:
代码如下:
{
xtype : 'treepanel', //使用treepanel
region : 'west', //定位
reference : 'fileTreeObj', //命名
// height:window.innerHeight*0.8-210, //随着外部容器大小变动
height : 470,
flex : 1,
rootVisible : false, // 是否显示根节点
bind : {
store : '{salaryItemTree}'
} // 数据源
,
listeners : {
itemclick : 'onSalaryItemTreeNodeClick' //监听树选择事件。忽略。。
},
tbar : [{ //树上增加tbar工具栏
xtype : 'triggerfield',
emptyText : '按名称查找筛选', //提示语
width : 150,
triggerCls : 'x-form-search-trigger', // 放大镜图标。可不需要
onTriggerClick : function() {
this.reset();
},
listeners : {
change : function() {
var tree = this.up('treepanel'), v, matches = 0;
try {
v = new RegExp(this.getValue(), 'i');
Ext.suspendLayouts();
tree.store.filter({
filterFn : function(node) {
var children = node.childNodes,
len = children && children.length,
visible = node.isLeaf() ? v.test(node.get('text')) : false, i;
for (i = 0; i < len && !(visible = children[i].get('visible')); i++);
if (visible && node.isLeaf()) {
matches++;
}
return visible;
},
id : 'titleFilter'
});
tree.down('#matches').setValue(matches);
Ext.resumeLayouts(true);
} catch (e) {
this.markInvalid('无匹配数据');
}
},
buffer : 500
// 延时
}
}, {
//匹配项显示内容。可隐藏。不可删除,删除需要对上面的change事件进行调整。
xtype : 'displayfield',
itemId : 'matches',
fieldLabel : '匹配项',
width : 100,
labelWidth : 50,
listeners : {
beforerender : function() {
var me = this, tree = me.up('treepanel'),
root = tree.getRootNode(),
leafCount = 0; //默认0个匹配项
tree.store.on('fillcomplete', function(store, node) {
if (node === root) {
root.visitPostOrder('',function(node) {
if (node.isLeaf()) {
leafCount++;
}
});
me.setValue(leafCount);
}
});
},
single : true
}
}]
}
其中tree的DataSource为初始化绑定上去的。
可在获取数据源后,迭代添加到treepanel控件上。迭代生成菜单树。具体根据数据来。这里只是参考。
//生成公式树
createSalaryItemTree:function(result){
var me = this, view = me.getView(), vm = me.getViewModel();
var salaryItemTree = vm.getStore('salaryItemTree');
var itemTreeRoot = salaryItemTree.getRoot();
//清除树
itemTreeRoot.removeAll();
//调用方法获取树的其他信息
Ext.each(result, function (record) {
var childrenData = record.children;
itemTreeChild = itemTreeRoot.appendChild({text:record.ItemName, id:record.ItemID,
leaf:record.isLeaf, expanded: false,categoryID:record.categoryID,categoryName:record.categoryName,
isRootNode:record.isRootNode, comboData:record.comboData });
if(childrenData != null){
me.addSalayTreeChild(itemTreeChild,childrenData);
}
})
},
//递归生成菜单树
addSalayTreeChild:function(child,childrenData){
var me = this;
Ext.each(childrenData,function(data){
var childrenData = data.children;
var child_Child = child.appendChild({text:data.ItemName, id:data.ItemID, leaf:data.isLeaf, expanded: false,
categoryID:data.categoryID,categoryName:data.categoryName,
isRootNode:data.isRootNode, comboData:data.comboData});
if(childrenData != null){
me.addSalayTreeChild(child_Child,childrenData);
}
})
}
当然。官方Demo的源码少不了的。有兴趣可以研究一下。
tbar: [{
labelWidth: 130,
xtype: 'triggerfield',
fieldLabel: 'Filter on thread title',
triggerCls: 'x-form-clear-trigger',
onTriggerClick: function() {
// Will trigger the change listener
this.reset();
},
listeners: {
change: function() {
var tree = this.up('treepanel'),
v,
matches = 0;
try {
v = new RegExp(this.getValue(), 'i');
Ext.suspendLayouts();
tree.store.filter({
filterFn: function(node) {
var children = node.childNodes,
len = children && children.length,
// Visibility of leaf nodes is whether they pass the test.
// Visibility of branch nodes depends on them having visible children.
visible = node.isLeaf() ? v.test(node.get('title')) : false,
i;
// We're visible if one of our child nodes is visible.
// No loop body here. We are looping only while the visible flag remains false.
// Child nodes are filtered before parents, so we can check them here.
// As soon as we find a visible child, this branch node must be visible.
for (i = 0; i < len && !(visible = children[i].get('visible')); i++);
if (visible && node.isLeaf()) {
matches++;
}
return visible;
},
id: 'titleFilter'
});
tree.down('#matches').setValue(matches);
Ext.resumeLayouts(true);
} catch (e) {
this.markInvalid('Invalid regular expression');
}
},
buffer: 250
}
}, {
xtype: 'displayfield',
itemId: 'matches',
fieldLabel: 'Matches',
// Use shrinkwrap width for the label
labelWidth: null,
listeners: {
beforerender: function() {
var me = this,
tree = me.up('treepanel'),
root = tree.getRootNode(),
leafCount = 0;
tree.store.on('fillcomplete', function(store, node) {
if (node === root) {
root.visitPostOrder('', function(node) {
if (node.isLeaf()) {
leafCount++;
}
});
me.setValue(leafCount);
}
});
},
single: true
}
}]