提示:针对dtree版本v2.5.7
文章目录
前言-下拉树实现描述
该需求应用于手机端页面展示,为了使页面样式加载平衡,使页面元素尽可能接近原生客户端效果,避免其他表单元素加载完成但下拉框加载慢导致的短暂空白块造成不好的用户体验。因此设计逻辑为进入页面先加载下拉框,然后获取数据再重新渲染下拉树。
$(function () {
initDtree();
});
var deDataRes = [];//区域树
function getAreaTree(){
$.ajax({
//... //ajax一系列操作
deDataRes = '新的树';
reloadDtree();
});
}
function initDtree(){
layui.extend({
dtree: '../resources/layui_ext/dtree/dtree' // {/}的意思即代表采用自有路径,即不跟随 base 路径
}).use(['dtree','layer','jquery'], function(){
var dtree = layui.dtree, layer = layui.layer, $ = layui.jquery;
// 初始化树
var DemoTree = dtree.renderSelect({
elem: "#demoTree",
selectTips: "--请选择--",
selectCardHeight: "150", //bug:指定展示框高度,当reload这棵树时,该值就无效,即使重新设值,新值也无效。gif中的高度是再通过css方式控制的。
data: [], // 使用data加载
// selectInitVal: "2600", // 你可以在这里指定默认值id
accordion: true, // 开启手风琴
none: "无数据...", //无数据提示
onlyIconControl : true,
// url: "../json/case/demoJson.json" // 使用url加载(可与data加载同时存在)
});
//
// 绑定节点点击(点击节点的文本才有效)
dtree.on("node('demoTree')" ,function(obj){
// layer.msg(JSON.stringify(obj.param));
console.log("obj.param==" + JSON.stringify(obj.param));
console.log("obj.param.nodeId==" + obj.param.nodeId);
let seld = '';
let selc = '';
let nowParam = layui.dtree.getNowParam('demoTree');//当前选中的树节点信息
console.log("nowParam==" + JSON.stringify(nowParam));
seld = nowParam.nodeId;
selc = nowParam.context;
if(!obj.param.leaf){
// //调用内置函数展开节点
// var $div = obj.dom;
// DemoTree.clickSpread($div);
} else {
// layer.msg("叶子节点就不展开了");
}
DemoTree.menubarMethod().closeAllNode();//收缩树
});
//点击任何地方关闭下拉树
$("body").on("click", function(event){
$("div[dtree-id][dtree-select]").removeClass("layui-form-selected");
$("div[dtree-id][dtree-card]").removeClass("dtree-select-show layui-anim layui-anim-upbit");
});
});
getAreaTree();
}
function reloadDtree(){
layui.use(['dtree'], function(){
layui.dtree.reload('demoTree',{
selectTips: '--请选择--',
data: deDataRes, // 使用data加载
selectInitVal: '2600', // 你可以在这里指定默认值id,如:2600是深圳的id
accordion: true, // 开启手风琴
none: "无数据...", //无数据提示
onlyIconControl : true,
done: function(){
//dtree.selectVal("demoTree", "值");
layui.dtree.selectVal('demoTree');//设置下拉树的初始展示值,如不传第二个参数,则树会自动根据当前选中节点回显值
}
});
});
}
一、单击选中bug
示例:
因为dtree下拉树在点击节点左侧“+”符号展开(而没有点击选中节点的文本)后,再次点击下拉动作会自动定位到该层级,导致非点击操作的切换效果;故不用下面的绑定点击事件dtree.on(…);方法获取选中值(该函数只针对点击节点的文本有效)。
这种情况就导致了用户再次展开下拉框的时候会跳跃地选中了莫名的值,带来了不好的体验。同时,发现单纯通过使用dtree.on(…);点击回调函数不是每次都能匹配到下拉框选中的值,这就带来了开发隐患。
解决可行方法一:在收缩下拉框的时候理论上应该手动调用DemoTree.menubarMethod().refreshTree(); 刷新树;由于本人没有找到收缩时的回调方法,所以采取getNowParam();的方式匹配上每次下拉框中选中的数据,这样在表单提交或数据处理时也方便操作。
二、使用reload()重新加载数据(data方式)
描述
:给一个已经初始化的dtree的下拉树重新渲染数据,在reload()后发现:下拉框的值出现重复,下拉树也出现重复树结构。示例,将网速调慢后加载页面,可以看到组件初始化后在重新加载数据时出现了下拉框重复值“深圳”、展开的重复树“广东”的现象:
分析
:在多次调试间发现,间歇性会出现这种情况,初步判断是资源加载或渲染问题。如果先加载数据再初始化组件、也就不用reload就屁事都没了😂,但为了更好的浏览体验,继续排查问题。由于不懂dtree内部逻辑,所以只能从初始化和重新渲染两个模块下手,通过查看文档及追踪,虽然值/树有重复但dtree-id是一样的,判断再重新渲染下拉树的Dom结构的时候出现了异常。
解决办法
:initDtree初始化下拉树时指定数据data为空数组[],这样在reload渲染中重新加载子节点就不会出现重复添加的情况了。
三、实现reload,严格控制reload在init后,否则会出现“方法获取失败,请检查ID或对象传递是否正确”。
这个点可以说是开发中因为疏忽导致的小问题,在此记录下。dtree.js: