媒介
近来公司做一个项目用到zTree,zTree功用壮大就不必多说了,置信用过的人都晓得。
公司项目由于要展现的节点异常多,所以请求要完成搜刮节点的功用,zTree确切很壮大,它供应了getNodesByParamByFuzzy要领可依据关键字举行隐约查询获得想要的节点,极为轻易。然则题目来了,由于要读取节点的数据量很大,节点的数目有几万个以至更多,考虑到机能和时候上的题目,因而不能一次性把悉数节点数据读取出来,这里我采纳的是zTree自带的分批异步加载形式。然则如许就又造成了别的一个题目,再运用getNodesByParamByFuzzy这个要领时便只能找到已加载出来的节点,而没法找到还没有举行加载的节点,从而运用户体验不好。
分批异步加载
加载一切父节点
为了处理这个题目,刚最先的主意是每次都去数据库查询数据,每次只显示搜刮到的第一条效果,然后再举行下一条查询,查到末了一条时又返回第一条,现实如许的思绪是行的通的,然则如许完成起来异常贫苦,而在项目中一般都不止一棵树,难不成每棵树都要如许,为了这小小的功用却要写云云多的代码着实恶心,空话不多说,下面是我本身想的以为比较好的要领。看下面代码:
// 节点加载完的回调函数,加载体式格局照旧是分批加载,然则不是等用户睁开节点才去加
// 载,而是让它自动完成加载,这里不好的处所是照旧要加载悉数数据,所以必需守候
// 它加载完才运用搜刮功用
function onAsyncSuccess(event, treeId, treeNode, msg) {
var zTreeObj = $.fn.zTree.getZTreeObj();
// 这个要领是将规范 JSON 嵌套花样的数据转换为简朴 Array 花样
var nodes = zTreeObj.transformToArray(zTreeObj.getNodes());
for (var i = 0; i < nodes.length; i++) {
// 推断节点是不是已加载过,假如已加载过则不须要再加载
if (!nodes[i].zAsync) {
zTreeObj.reAsyncChildNodes(nodes[i], '', true);
}
}
}
守候悉数树节点加载完
所以还必需定义多一个推断树节点是不是已悉数加载完的要领。这个要领我是参考《通晓JavaScript》上面关于守候页面加载完的要领来写的。
function treeAsyncReady(treeId, f) {
// 假如树已加载完,立时实行函数
if (treeAsyncReady.done) {
return f();
}
var zTreeObj = $.fn.zTree.getZTreeObj();
treeAsyncReady.timer = setInterval(function() {
if (treeAsyncReady.done) {
return false;
}
// 猎取没有异步加载过的节点
var nodes = zTreeObj.getNodesByFilter(funciton(node) {
return !node.zAsync;
});
// 假如节点数为零则申明已加载完
if (nodes.length == 0) {
clearInterval(treeAsyncReady.timer);
treeAsyncReady.timer == null;
// 实行函数
f();
treeAsyncReady.done = true;
}
}, 13);
}
完成搜刮功用
定义了这个要领,然后就能够在这个要领完成完成你要搜刮的功用了。
treeAsyncReady('treeId', function() {
// 在这里写搜刮节点的代码
...
});
搜刮节点
搜刮节点的功用请求依据关键字隐约婚配节点,而且要睁开节点地点的父节点直到根节点。
function swarchNodes(treeId, keyword) {
var zTreeObj = $.fn.zTree.getZTreeObj();
// 去掉上一次查询到的节点色彩,假如是第一次搜刮则不必
if (searchNodes.nodes) {
var prevNodes = searchNodes.nodes;
for (var i = 0; i < prevNodes.length; i++) {
prevNodes[i].highlight = false;
zTreeObj.updateNode(prevNodes[i]);
}
// 收起悉数节点
zTreeObj.expandAll(false);
}
// 从新查找节点
var nodes = zTreeObj.getNodesByParamFuzzy('name', $.trim(keyword));
for (var i = 0; i < nodes.length; i++) {
nodes[i].highlight = true;
zTreeObj.updateNode(nodes[i]);
// 推断是不是是根节点,假如是根节点则不必睁开
if (nodes[i].level != 0) {
// 本身定义的一个查找悉数父节点的要领
var parentNodes = getParentNodes(treeId, nodes[i]);
// **这里重要睁开节点时必需先从根节点最先睁开,不然会出题目**
for (var j = parentNodes.length - 1; j >= 0; j--) {
// 睁开没有睁开的父节点
if (!parentNodes[j].open) {
zTreeObj.expandNode(parentNodes[j], true, false, false);
}
}
}
}
// 缓查找到的节点
searchNodes.nodes = nodes;
}
查找悉数父节点
这个要领是查找节点的悉数父节点,直到根父节点。
function getParentNodes(treeId, node, cache) {
// 缓存变量
cache = cache || [];
var zTreeObj = $.fn.zTree.getZTreeObj();
var parentNode = node.getParentNode();
// 有父节点则缓存,直到根节点
if (parentNode != null) {
cache.push(parentNode);
} else {
return cache;
}
// 递归挪用查找父节点
return getParentNodes(treeId, parentNode, cache);
}