贝利信息

如何在 TreeView 折叠时隐藏加载图标(Loading Icon)

日期:2026-01-17 00:00 / 作者:霞舞

本文介绍如何通过引入状态标志(flag)精准控制 treeview 展开/折叠时的加载图标显示逻辑,确保仅在展开子节点时显示旋转加载动画,折叠时不触发任何加载态,从而提升用户体验与交互准确性。

在基于 jQuery 实现的 TreeView 组件中,常见做法是在点击父节点时统一显示加载图标(如 Font Awesome 的 fa-spinner fa-spin),再通过 setTimeout 延迟移除并执行 slideToggle 动画。但原始实现未区分「展开」与「折叠」状态,导致每次点击都插入 .loading 元素——这不仅造成视觉冗余,还可能引发 DOM 冗余或样式冲突。

核心解决方案:为每个可折叠分支(

  • )维护独立的状态标志(flag)
  • ,用于记录当前是否处于「已展开」状态。该 flag 必须声明在 tree.find('li').has("ul").each(...) 的迭代作用域内,确保每个分支拥有私有状态,避免相互干扰。

    以下是关键逻辑重构说明:

    状态隔离

    tree.find('li').has("ul").each(function () {
      var branch = $(this);
      let flag = false; // ✅ 每个分支独享 flag,不可提至外层!
      branch.on('click', function (e) {
        if (this === e.target) {
          flag = !flag; // 点击即切换状态
          // ...
        }
      });
    });

    条件化加载图标注入
    仅当 flag === true(即本次操作为「展开」)时插入 loading 元素;折叠时直接执行收起动画,不添加、不移除加载元素:

    if (flag) {
      $(this).append("");
      setTimeout(() => {
        $(this).find('.loading').remove();
        $(this).children().children().slideToggle(400);
      }, 400);
    } else {
      $(this).children().children().slideToggle(400); // 无 loading,直切动画
    }

    ⚠️ 注意事项

    完整精简版插件片段(含注释)

    $.fn.extend({
      treed: function (options) {
        const opts = $.extend({
          openedClass: 'fa-minus-circle',
          closedClass: 'fa-plus-circle'
        }, options);
    
        return this.each(function () {
          const $tree = $(this).addClass('tree');
          $tree.find('li').has('ul').each(function () {
            const $branch = $(this);
            $branch
              .prepend(``)
              .addClass('branch');
    
            let isOpen = false; // 分支级状态标识
    
            $branch.on('click', function (e) {
              if (e.target !== this) return;
    
              isOpen = !isOpen;
              const $icon = $branch.children('i:first');
              $icon.toggleClass(`${opts.openedClass} ${opts.closedClass}`);
    
              if (isOpen) {
                // 展开:显示 loading → 延迟移除 → 执行展开动画
          

    $branch.append(''); setTimeout(() => { $branch.find('.loading').remove(); $branch.children('ul').slideDown(400); }, 400); } else { // 折叠:直接收起,不触发 loading $branch.children('ul').slideUp(400); } }); // 初始化:默认收起子列表 $branch.children('ul').hide(); }); }); } });

    最后,初始化时可传入自定义图标类:

    $('#tree2').treed({
      openedClass: 'fa-folder-open',
      closedClass: 'fa-folder'
    });

    通过该方案,TreeView 的加载反馈变得语义清晰、行为可控——用户能明确感知“正在加载新内容”仅发生在展开动作中,折叠则即时响应,无任何视觉延迟或干扰,符合现代 Web 交互设计最佳实践。