LayUi 树形组件tree 实现懒加载模式,展开父节点时异步加载子节点数据
LayUi框架中树形组件tree官方还在持续完善中,目前最新版本为v2.5.5
官方树形组件目前还不支持懒加载方式,之前我修改一版是通过reload重载实例方法填充子节点数据方式,因为递归页面元素时存在效率问题,最终放弃升级。
本次重新star了官方最新tree.js源码,在其基础上扩展了子节点懒加载模式方法,data数据参数中增加了lazy: true,开启懒加载模式,需要配合spread事件使用。
部分源码修改截图:



调用例子:
<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
<meta name="renderer" content="webkit|ie-comp|ie-stand">
<meta http-equiv="hg-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta http-equiv="Cache-Control" content="no-siteapp" />
<link rel="stylesheet" href="./css/font.css">
<link rel="stylesheet" href="../lib/layui/css/layui.css" media="all">
<link rel="stylesheet" href="./lib/admin/admin.css" media="all">
<link rel="stylesheet" href="./lib/Scrollbar/jquery.scrollbar.css">
<script type="text/javascript" src="./lib/admin/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="./lib/Scrollbar/jquery.scrollBar.js"></script>
<script type="text/javascript" src="./lib/layui/layui.js"></script>
<script type="text/javascript" src="./lib/admin/admin.js"></script>
<!--[if lt IE 9]>
<script src="https://cdn.staticfile.org/html5shiv/r29/html5.min.js"></script>
<script src="https://cdn.staticfile.org/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<style>
.demo-tree{
width: 500px; height: 200px;
}
.demo-tree-box{
width: 500px; height: 200px;border: 1px #eee solid;overflow-y: auto;
}
.demo-input-tree{
height: auto;
width: 100%;
display: none;
position: absolute;
top: 100%;
background-color: #fff;
z-index: 100;
max-height: 400px;
}
.layui-input{
width: 500px;
cursor: pointer;
}
</style>
</head> <body class="layui-body-content">
<div class="layui-fluid">
<div class="layui-card">
<div class="layui-form layui-card-header layui-card-header-auto">
<div class="layui-form-item">
<label class="layui-form-label">部门:</label>
<div class="layui-inline">
<input type="text" name="dept" lay-verify="required" placeholder="请选择部门" autocomplete="off" class="layui-input" readonly="true">
<div id="treeinputid" class="demo-input-tree demo-tree-box"></div>
</div>
<div class="layui-inline layui-show-xs-block">
<button class="layui-btn layui-btn-lg layui-btn-normal" lay-submit lay-filter="sreach"><i
class="layui-icon layui-icon-lg"></i></button>
</div>
</div>
</div>
<div class="layui-card-body">
<div class="layui-card-header">
<button class="layui-btn layui-btn-lg layui-btn-normal"
onclick="getChecked()"><i
class="layui-icon"></i>获取选中</button>
<button class="layui-btn layui-btn-lg layui-btn-warm" onclick="setChecked()"><i
class="layui-icon"></i>设置节点勾选</button>
<button class="layui-btn layui-btn-lg layui-btn-danger" onclick="reload()"><i
class="layui-icon"></i>实例重载</button>
</div>
<div class="demo-tree">
<div id="treeid" class="demo-tree demo-tree-box"></div>
</div>
</div>
</div>
<div class="layui-floor">
<blockquote class="layui-elem-quote layui-quote-nm">Copyright©2019-2020, 本系统由@一如既往,提供技术支持!
</blockquote>
</div>
</div>
</body>
<script>
//初始化
layui.use(['tree'], function () {
var tree = layui.tree;
//treeid
var inst1 = tree.render({
elem: '#treeid',
id: 'treeid', //定义索引
showCheckbox: true, //是否显示复选框
showLine: true, //是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。
accordion: false, //是否开启手风琴模式,默认 false
onlyIconControl: false, //是否仅允许节点左侧图标控制展开收缩。默认 false
isJump: false, //是否允许点击节点时弹出新窗口跳转。默认 false
data: [{
id: 'hg-100',
field: '1',
level: '1',
title: '父节点100',
spread: true,
children: [{
id: 'hg-100101',
field: '3',
level: '2',
title: '子节点100101',
children: [{
id: 'hg-100101101',
field: '4',
level: '3',
title: '子节点100101101'
}, {
id: 'hg-100101102',
field: '5',
level: '3',
title: '子节点100101102'
}, {
id: 'hg-100101103',
field: '6',
level: '3',
title: '子节点100101103'
}]
}]
}, {
id: 'hg-200',
field: '2',
level: '1',
title: '父节点200',
lazy: true
}],
text: {
defaultNodeName: '无数据',
none: '加载数据失败!'
},
click: function (obj) {
console.log(obj.data); //得到当前点击的节点数据
console.log(obj.state); //得到当前节点的展开状态:open、close、normal
console.log(obj.elem); //得到当前节点元素
console.log(obj.data.children); //当前节点下是否有子节点
},
oncheck: function (obj) {
console.log(obj.data); //得到当前点击的节点数据
console.log(obj.checked); //得到当前节点的展开状态:open、close、normal
console.log(obj.elem); //得到当前节点元素
},
spread: function (obj) {
console.log(obj);
if(obj.state=='open'){
setTimeout(() => {
tree.lazytree(inst1.config.id, obj.elem, getTreeJson(obj.data.id));
}, 2000);
}
}
}); //treeinput
var inst2;
$("[name='dept']").on("click",function (e) {
e.stopPropagation();
const deprt = this;
if(!inst2){
inst2 = tree.render({
elem: '#treeinputid',
id: 'treeinputid', //定义索引
showCheckbox: true, //是否显示复选框
showLine: true, //是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。
accordion: false, //是否开启手风琴模式,默认 false
onlyIconControl: false, //是否仅允许节点左侧图标控制展开收缩。默认 false
isJump: false, //是否允许点击节点时弹出新窗口跳转。默认 false
data: [{
id: 'hg-100',
field: '1',
level: '1',
title: '父节点100',
spread: true,
children: [{
id: 'hg-100101',
field: '3',
level: '2',
title: '子节点100101',
children: [{
id: 'hg-100101101',
field: '4',
level: '3',
title: '子节点100101101'
}, {
id: 'hg-100101102',
field: '5',
level: '3',
title: '子节点100101102'
}, {
id: 'hg-100101103',
field: '6',
level: '3',
title: '子节点100101103'
}]
}]
}, {
id: 'hg-200',
field: '2',
level: '1',
title: '父节点200',
lazy: true
}],
text: {
defaultNodeName: '无数据',
none: '加载数据失败!'
},
click: function (obj) {
console.log(obj.data); //得到当前点击的节点数据
console.log(obj.state); //得到当前节点的展开状态:open、close、normal
console.log(obj.elem); //得到当前节点元素
console.log(obj.data.children); //当前节点下是否有子节点
},
oncheck: function (obj) {
var checkData = tree.getChecked(inst2.config.id);
var map = getmap(checkData);
$(deprt).val(map.value.join(','));
},
spread: function (obj) {
console.log(obj);
if(obj.state=='open'){
setTimeout(() => {
tree.lazytree(inst2.config.id, obj.elem, getTreeJson(obj.data.id));
}, 2000);
}
}
});
}
$("#treeinputid").toggle();
}) //监听表单提交事件
hg.form.onsubmit('sreach', function (data) {
$("#treeinputid").hide();
var checkData = tree.getChecked(inst2.config.id);
var map = getmap(checkData);
var init = map.result;
hg.msg(JSON.stringify(init));
}); const getmap = (target, result = []) => {
layui.each(target,(i,e)=>{
e.id && result.push({id:e.id,title:e.title});
e.children && getmap(e.children, result);
});
let titles = result.map(e=>{return e.title});
return {value:titles,result:result};
}; }); // 模拟后台返回数据
function getTreeJson(id) {
if (id === 'hg-200') {
return [{
id: 'hg-200101',
level: '2',
title: '子节点200101'
}, {
id: 'hg-200102',
level: '2',
title: '子节点200102',
lazy: true
}];
}
if (id === 'hg-200102') {
return [{
id: 'hg-200102101',
level: '3',
title: '子节点200102101'
}, {
id: 'hg-200102102',
level: '3',
title: '子节点200102102',
lazy: true
}];
}
if (id === 'hg-200102102') {
return [{
id: 'hg-200102102101',
level: '4',
title: '子节点200102102101'
}, {
id: 'hg-200102102102',
level: '4',
title: '子节点200102102102',
}];
}
}
//获得选中的节点
function getChecked(){
layui.use(['tree'], function () {
var tree = layui.tree;
var checkData = tree.getChecked('treeid');
hg.msg(JSON.stringify(checkData));
});
}
//设置节点勾选
function setChecked(){
layui.use(['tree'], function () {
var tree = layui.tree;
tree.setChecked('treeid', ['hg-100101101','hg-100101102']);
});
}
//实例重载
function reload(){
layui.use(['tree'], function () {
var tree = layui.tree;
tree.reload('treeid', {
});
});
} </script> </html>
<script>
//初始化
layui.use(['tree'], function () {
var tree = layui.tree;
//treeid
var inst1 = tree.render({
elem: '#treeid',
id: 'treeid', //定义索引
showCheckbox: true, //是否显示复选框
showLine: true, //是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。
accordion: false, //是否开启手风琴模式,默认 false
onlyIconControl: false, //是否仅允许节点左侧图标控制展开收缩。默认 false
isJump: false, //是否允许点击节点时弹出新窗口跳转。默认 false
data: [{
id: 'hg-100',
field: '1',
level: '1',
title: '父节点100',
spread: true,
children: [{
id: 'hg-100101',
field: '3',
level: '2',
title: '子节点100101',
children: [{
id: 'hg-100101101',
field: '4',
level: '3',
title: '子节点100101101'
}, {
id: 'hg-100101102',
field: '5',
level: '3',
title: '子节点100101102'
}, {
id: 'hg-100101103',
field: '6',
level: '3',
title: '子节点100101103'
}]
}]
}, {
id: 'hg-200',
field: '2',
level: '1',
title: '父节点200',
lazy: true
}],
text: {
defaultNodeName: '无数据',
none: '加载数据失败!'
},
click: function (obj) {
console.log(obj.data); //得到当前点击的节点数据
console.log(obj.state); //得到当前节点的展开状态:open、close、normal
console.log(obj.elem); //得到当前节点元素
console.log(obj.data.children); //当前节点下是否有子节点
},
oncheck: function (obj) {
console.log(obj.data); //得到当前点击的节点数据
console.log(obj.checked); //得到当前节点的展开状态:open、close、normal
console.log(obj.elem); //得到当前节点元素
},
spread: function (obj) {
console.log(obj);
if(obj.state=='open'){
setTimeout(() => {
tree.lazytree(inst1.config.id, obj.elem, getTreeJson(obj.data.id));
}, 2000);
}
}
}); //treeinput
var inst2;
$("[name='dept']").on("click",function (e) {
e.stopPropagation();
const deprt = this;
if(!inst2){
inst2 = tree.render({
elem: '#treeinputid',
id: 'treeinputid', //定义索引
showCheckbox: true, //是否显示复选框
showLine: true, //是否开启连接线。默认 true,若设为 false,则节点左侧出现三角图标。
accordion: false, //是否开启手风琴模式,默认 false
onlyIconControl: false, //是否仅允许节点左侧图标控制展开收缩。默认 false
isJump: false, //是否允许点击节点时弹出新窗口跳转。默认 false
data: [{
id: 'hg-100',
field: '1',
level: '1',
title: '父节点100',
spread: true,
children: [{
id: 'hg-100101',
field: '3',
level: '2',
title: '子节点100101',
children: [{
id: 'hg-100101101',
field: '4',
level: '3',
title: '子节点100101101'
}, {
id: 'hg-100101102',
field: '5',
level: '3',
title: '子节点100101102'
}, {
id: 'hg-100101103',
field: '6',
level: '3',
title: '子节点100101103'
}]
}]
}, {
id: 'hg-200',
field: '2',
level: '1',
title: '父节点200',
lazy: true
}],
text: {
defaultNodeName: '无数据',
none: '加载数据失败!'
},
click: function (obj) {
console.log(obj.data); //得到当前点击的节点数据
console.log(obj.state); //得到当前节点的展开状态:open、close、normal
console.log(obj.elem); //得到当前节点元素
console.log(obj.data.children); //当前节点下是否有子节点
},
oncheck: function (obj) {
var checkData = tree.getChecked(inst2.config.id);
var map = getmap(checkData);
$(deprt).val(map.value.join(','));
},
spread: function (obj) {
console.log(obj);
if(obj.state=='open'){
setTimeout(() => {
tree.lazytree(inst2.config.id, obj.elem, getTreeJson(obj.data.id));
}, 2000);
}
}
});
}
$("#treeinputid").toggle();
}) //监听表单提交事件
hg.form.onsubmit('sreach', function (data) {
$("#treeinputid").hide();
var checkData = tree.getChecked(inst2.config.id);
var map = getmap(checkData);
var init = map.result;
hg.msg(JSON.stringify(init));
}); const getmap = (target, result = []) => {
layui.each(target,(i,e)=>{
e.id && result.push({id:e.id,title:e.title});
e.children && getmap(e.children, result);
});
let titles = result.map(e=>{return e.title});
return {value:titles,result:result};
}; }); // 模拟后台返回数据
function getTreeJson(id) {
if (id === 'hg-200') {
return [{
id: 'hg-200101',
level: '2',
title: '子节点200101'
}, {
id: 'hg-200102',
level: '2',
title: '子节点200102',
lazy: true
}];
}
if (id === 'hg-200102') {
return [{
id: 'hg-200102101',
level: '3',
title: '子节点200102101'
}, {
id: 'hg-200102102',
level: '3',
title: '子节点200102102',
lazy: true
}];
}
if (id === 'hg-200102102') {
return [{
id: 'hg-200102102101',
level: '4',
title: '子节点200102102101'
}, {
id: 'hg-200102102102',
level: '4',
title: '子节点200102102102',
}];
}
}
//获得选中的节点
function getChecked(){
layui.use(['tree'], function () {
var tree = layui.tree;
var checkData = tree.getChecked('treeid');
hg.msg(JSON.stringify(checkData));
});
}
//设置节点勾选
function setChecked(){
layui.use(['tree'], function () {
var tree = layui.tree;
tree.setChecked('treeid', ['hg-100101101','hg-100101102']);
});
}
//实例重载
function reload(){
layui.use(['tree'], function () {
var tree = layui.tree;
tree.reload('treeid', {
});
});
} </script>


【HG-Layui-UI通用后台管理框架V1.0版】
下载地址:
https://www.cnblogs.com/han1982/p/12003454.html
tree.js 下载地址在回复区可见。(layui-v2.5.5版本替换tree.js可用)
LayUi 树形组件tree 实现懒加载模式,展开父节点时异步加载子节点数据的更多相关文章
- JQuery/JS插件 jsTree加载树,预先加载,初始化时加载前三级节点,当展开第三级节点时 就加载该节点下的所有子节点
jsTree加载树, 初始化时 加载前三级节点, 当展开第三级节点时 就加载该节点下的所有子节点 html: <!DOCTYPE html> <html> <head&g ...
- 修复使用<code>XmlDocument</code>加载含有DOCTYPE的Xml时,加载后增加“[]”字符的错误
C# LINQ TO XML - Remove “[]” characters from the DTD header http://stackoverflow.com/questions/12358 ...
- zTree设置异步加载后展开
//不能直接配置展开属性 因为没有数据,需要添加回调函数,异步加载成功展开 callback: { onAsyncSuccess: zTreeOnAsyncSuccess } //异步加载成功回调函数 ...
- 【EasyUI学习-2】Easyui Tree的异步加载
作者:ssslinppp 1. 摘要 2. tree的相关介绍 3. 异步加载tree数据,并实现tree的折叠展开 3.1 功能说明: 3.2 前台代码 3.3 后台代码 4. 其他 1 ...
- EasyUI之树形结构tree
转自:https://blog.csdn.net/ya_1249463314/article/details/70305730 版权声明:本文为博主原创文章,未经博主允许不得转载. https://b ...
- 多线程异步加载图片async_pictures
异步加载图片 目标:在表格中异步加载网络图片 目的: 模拟 SDWebImage 基本功能实现 理解 SDWebImage 的底层实现机制 SDWebImage 是非常著名的网络图片处理框架,目前国内 ...
- ztree异步加载树节点
参考文档:https://www.cnblogs.com/tenWood/p/8620708.html ztree api地址:http://www.treejs.cn/v3/api.php 说明:j ...
- [翻译]Bitmap的异步加载和缓存
内容概述 [翻译]开发文档:android Bitmap的高效使用 本文内容来自开发文档"Traning > Displaying Bitmaps Efficiently", ...
- Jquery Ztree异步加载树
1. 下载jquery的JS文件/ztree的CSS文件和JS文件 https://jquery.com/download/ https://gitee.com/zTree/zTree_v3/tree ...
随机推荐
- C#线程学习笔记四:线程同步
本笔记摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/21/ThreadsSynchronous.html,记录一下学习过程以备后续查用. ...
- day 28-1 元类
元类 元类的用途:自定义元类控制类的创建行为及类的实例化行为 Python 中一切皆为对象. 一切接对象,对象可以怎么用呢? 1.都可以被引用,x=obj 2.都可以当作函数的参数传入 3.都可以当作 ...
- mysql-5.7.21-winx64安装教程
1 . 下载对用的版本信息 地址是:https://dev.mysql.com/downloads/mysql/ 2 . 解压到目录 D:\tools\mysql\mysql-5.7.21-winx6 ...
- Android Healthd电池服务分析
healthd healthd是安卓4.4之后提出来的,监听来自kernel的电池事件,并向上传递电池数据给framework层的BatteryService.BatteryService计算电池电量 ...
- [AI开发]DeepStream开发填坑记录
下面是在deepstream使用过程中碰到的一些坑: (1)Pipeline中的Sink如果需要编码存文件或者推rtmp的流,注意控制编码的参数,编码质量不要太高.否则可能Sink带不动,整个Pipe ...
- 利用keras自带影评数据集进行评价正面与否的二分类训练
from keras.datasets import imdb from keras import layers from keras import models from keras import ...
- Java面向对象之继承(一)
目录 Java面向对象之继承 引言 继承的特点 语法格式 父子类的关系 继承要点 重写父类方法 继承中的构造器 继承中的super关键字 ... Java面向对象之继承 继承是面向对象的第二大特征,是 ...
- 网站后台getshell
phpmyadmin后台Getshell 获取 web 绝对路径 select @@basedir; 检测是否有写入权限 show global variables like 'secure%' ## ...
- JavaWeb 错误/异常时页面提示
经常我们会遇到发生页面404错误,服务器 500 异常,如果默认方式处理,则是将异常捕获之后跳到 Tomcat 缺省的异常页面,如下图所示.
- Android开发之OkHttp介绍
要论时下最火的网络请求框架,当属OkHttp了.自从Android4.4开始,google已经开始将源码中的HttpURLConnection替换为OkHttp,而在Android6.0之后的SDK中 ...