SmartAdmin Treeview实现仅单个父节点完全展开
Treeview 同层单展(手风琴)效果实现
原有代码问题说明
你之前的两个测试方案都没达到效果,核心问题出在节点查找范围不对:
- 全量遍历所有
li的方案:查找范围覆盖了所有层级的节点,没有限定为当前节点的同级节点,也没有排除当前点击的目标节点,且遍历逻辑里引用的children是当前点击节点的子元素,不是遍历到的其他节点的子元素,逻辑不生效 - 固定查找顶层
li下ul的方案:只针对顶层节点做折叠,不管点击哪一层级的节点都会折叠顶层展开项,点击深层子节点时就会出现不符合预期的全局折叠
修正后的实现代码
核心逻辑是:展开当前节点前,仅查找和当前父节点同层级的已展开节点做折叠,不跨层级操作,也不会误处理当前节点。
$('.tree > ul').attr('role', 'tree').find('ul').attr('role', 'group'); $('.tree').find('li:has(ul)').addClass('parent_li').attr('role', 'treeitem').find(' > span').attr('title', 'Collapse this branch').on('click', function (e) { const currentSpan = $(this); const parentLi = currentSpan.parent('li.parent_li'); const childContainer = parentLi.find(' > ul'); const childItems = childContainer.find(' > li'); if (childItems.is(':visible')) { // 折叠当前已展开的节点 childItems.hide('fast'); parentLi.attr("expanded", 'false'); currentSpan.attr('title', 'Expand this branch') .find(' > i') .removeClass() .addClass('fa fa-lg fa-plus-circle'); } else { // 折叠同层级下所有其他已展开的父节点 parentLi.siblings('li.parent_li[expanded="true"]').each(function () { const otherLi = $(this); otherLi.find('> ul > li').hide('fast'); otherLi.attr('expanded', 'false') .find('> span') .attr('title', 'Expand this branch') .find('> i') .removeClass() .addClass('fa fa-lg fa-plus-circle'); }); // 展开当前点击的节点 childItems.show('fast'); childContainer.attr("style", 'display: grid'); parentLi.attr("expanded", 'true'); currentSpan.attr('title', 'Collapse this branch') .find(' > i') .removeClass() .addClass('fa fa-lg fa-minus-circle'); } e.stopPropagation(); });
逻辑说明
- 用
siblings()方法获取当前节点的同级元素,自动排除当前节点本身,不需要额外写判断过滤 - 选择器加了
[expanded="true"]过滤,只处理已经处于展开状态的节点,减少不必要的DOM操作 - 折叠其他节点时同步更新
expanded属性、提示文案、图标样式,保证UI状态和属性状态一致 - 该逻辑对所有层级的节点生效,不管点击顶层还是深层的父节点,都只会折叠同层级的其他展开项,不会影响其他层级的展开状态,不会出现点击子节点全局折叠的问题
内容的提问来源于stack exchange,提问作者ScuffedCoder
相关产品推荐
相关产品推荐

