layui树形异步:动态加载子树节点

layui树形异步:动态加载子树节点

【免费下载链接】layui 一套遵循原生态开发模式的 Web UI 组件库,采用自身轻量级模块化规范,易上手,可以更简单快速地构建网页界面。 【免费下载链接】layui 项目地址: https://gitcode.com/GitHub_Trending/la/layui

还在为海量数据树形组件加载缓慢而烦恼?layui树组件的异步加载功能让你的应用性能飞升!

痛点场景:大数据量树形结构的性能瓶颈

在实际Web应用开发中,我们经常遇到这样的场景:

  • 组织架构树:成千上万的部门和员工数据
  • 商品分类树:海量商品分类层级结构
  • 地区选择器:全国省市区县四级联动
  • 权限管理树:复杂的菜单权限层级

传统的一次性加载所有节点数据的方式会导致:

  • ⏳ 页面加载时间过长
  • 💾 内存占用急剧上升
  • 📉 用户体验严重下降

layui树组件异步加载解决方案

layui树组件提供了优雅的异步加载机制,通过动态请求子树数据,实现按需加载,完美解决大数据量场景的性能问题。

核心实现原理

mermaid

基础异步加载实现

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>layui树形异步加载示例</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/layui@2.9.7/src/css/layui.css">
</head>
<body>

<div id="async-tree"></div>

<script src="https://cdn.jsdelivr.net/npm/layui@2.9.7/src/layui.js"></script>
<script>
layui.use(['tree', 'jquery', 'layer'], function(){
  var tree = layui.tree;
  var $ = layui.$;
  var layer = layui.layer;

  // 初始只加载第一层数据
  var initialData = [
    {
      title: '部门管理',
      id: 'dept',
      spread: false,
      children: [] // 初始为空,点击时异步加载
    },
    {
      title: '用户管理', 
      id: 'user',
      spread: false,
      children: [] // 初始为空,点击时异步加载
    }
  ];

  tree.render({
    elem: '#async-tree',
    data: initialData,
    id: 'async-tree-id',
    click: function(obj){
      var node = obj.data;
      
      // 如果节点没有子数据且未被加载过
      if ((!node.children || node.children.length === 0) && !node._loaded) {
        loadChildrenAsync(node, obj.elem);
      }
    }
  });

  // 异步加载子节点函数
  function loadChildrenAsync(node, elem) {
    // 显示加载中状态
    var loadingIndex = layer.load(1, {
      shade: [0.1, '#fff']
    });

    // 模拟异步请求
    $.ajax({
      url: '/api/tree/children?id=' + node.id,
      type: 'GET',
      success: function(response) {
        layer.close(loadingIndex);
        
        if (response.code === 0 && response.data) {
          // 标记节点已加载
          node._loaded = true;
          node.children = response.data;
          
          // 重新渲染树
          tree.reload('async-tree-id', {
            data: initialData
          });
        }
      },
      error: function() {
        layer.close(loadingIndex);
        layer.msg('加载失败,请重试');
      }
    });
  }
});
</script>
</body>
</html>

完整异步树组件封装

对于更复杂的业务场景,我们可以封装一个可复用的异步树组件:

/**
 * 异步树组件封装
 * @param {Object} options 配置选项
 */
function AsyncTree(options) {
  this.config = $.extend({
    elem: '',
    url: '/api/tree/data',
    rootId: 'root',
    autoLoadRoot: true,
    // 其他配置...
  }, options);
  
  this.init();
}

AsyncTree.prototype = {
  init: function() {
    this.renderTree();
    if (this.config.autoLoadRoot) {
      this.loadNodeChildren(this.config.rootId);
    }
  },
  
  renderTree: function() {
    var that = this;
    this.tree = layui.tree.render({
      elem: this.config.elem,
      data: [],
      click: function(obj) {
        that.onNodeClick(obj);
      }
    });
  },
  
  onNodeClick: function(obj) {
    var node = obj.data;
    if (!node._loaded && (!node.children || node.children.length === 0)) {
      this.loadNodeChildren(node.id, obj.elem);
    }
  },
  
  loadNodeChildren: function(nodeId, elem) {
    var that = this;
    var loading = elem ? $(elem).find('.layui-tree-icon') : null;
    
    if (loading) {
      loading.addClass('layui-icon-loading layui-anim layui-anim-rotate');
    }
    
    $.get(this.config.url, { parentId: nodeId }, function(response) {
      if (loading) {
        loading.removeClass('layui-icon-loading layui-anim layui-anim-rotate');
      }
      
      if (response.success) {
        that.updateTreeData(nodeId, response.data);
      }
    });
  },
  
  updateTreeData: function(parentId, childrenData) {
    // 更新树数据逻辑
    // 这里需要实现递归查找并更新节点数据
  }
};

服务端API设计规范

为了实现良好的异步树支持,服务端API应该遵循以下规范:

参数类型必填说明
parentIdstring父节点ID,根节点可为空或特定值
pagenumber分页页码(支持大数据量分页加载)
sizenumber每页大小

响应数据格式:

{
  "code": 0,
  "msg": "success",
  "data": [
    {
      "id": "dept_001",
      "title": "技术部",
      "children": [], // 可为空,表示还有子节点
      "hasChildren": true, // 明确指示是否有子节点
      "spread": false
    }
  ]
}

性能优化技巧

  1. 数据分页加载
// 支持分页的异步加载
function loadChildrenWithPagination(node, page = 1) {
  $.get('/api/tree/children', {
    parentId: node.id,
    page: page,
    size: 20
  }, function(response) {
    // 处理分页数据
  });
}
  1. 缓存已加载数据
var treeCache = {};

function getNodeChildren(nodeId) {
  if (treeCache[nodeId]) {
    return Promise.resolve(treeCache[nodeId]);
  }
  
  return $.get('/api/tree/children', { id: nodeId })
    .then(function(data) {
      treeCache[nodeId] = data;
      return data;
    });
}
  1. 防抖处理频繁操作
var loadDebounce = null;

function onNodeClick(obj) {
  clearTimeout(loadDebounce);
  loadDebounce = setTimeout(function() {
    // 实际加载逻辑
  }, 300);
}

完整示例:组织架构异步树

<div class="layui-card">
  <div class="layui-card-header">组织架构树(异步加载)</div>
  <div class="layui-card-body">
    <div id="org-tree" style="min-height: 400px;"></div>
  </div>
</div>

<script>
layui.use(['tree', 'jquery'], function(){
  var tree = layui.tree;
  var $ = layui.$;
  
  var orgTree = tree.render({
    elem: '#org-tree',
    data: [{
      title: '全公司',
      id: 'root',
      spread: true,
      children: [] // 初始为空
    }],
    click: function(obj){
      var node = obj.data;
      
      // 只有点击箭头图标时才加载
      if (obj.state === 'open' && !node._loaded) {
        loadOrganizationChildren(node.id, function(children) {
          node.children = children;
          node._loaded = true;
          tree.reload('org-tree', {
            data: [node]
          });
        });
      }
    }
  });

  // 加载组织子节点
  function loadOrganizationChildren(parentId, callback) {
    $.ajax({
      url: '/api/organization/children',
      data: { parentId: parentId },
      success: function(response) {
        if (response.success) {
          callback(response.data);
        }
      }
    });
  }
});
</script>

总结对比:同步 vs 异步加载

特性同步加载异步加载
初始化性能差(数据量大时)优(按需加载)
内存占用
用户体验首次加载慢流畅按需加载
适用场景数据量小(<1000节点)大数据量层级结构
实现复杂度简单中等

最佳实践建议

  1. 合理设置初始层级:根据业务场景,预先加载2-3层常用数据
  2. 添加加载状态提示:使用旋转图标或文字提示用户正在加载
  3. 错误处理机制:网络异常时提供重试功能
  4. 缓存策略:对已加载的数据进行缓存,避免重复请求
  5. 分页支持:超大数据量时支持分页加载

通过layui树组件的异步加载功能,你可以轻松应对各种复杂的大数据量树形结构场景,为用户提供流畅的操作体验。立即尝试将这些技巧应用到你的项目中,让树形组件性能得到质的提升!

提示:在实际项目中,请根据具体业务需求调整异步加载策略,平衡用户体验和数据完整性。

【免费下载链接】layui 一套遵循原生态开发模式的 Web UI 组件库,采用自身轻量级模块化规范,易上手,可以更简单快速地构建网页界面。 【免费下载链接】layui 项目地址: https://gitcode.com/GitHub_Trending/la/layui

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值