You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Yii2中使用JQuery实现树形视图层级显示异常求助

修复Yii2中TreeView子级显示位置错误的问题

我帮你排查了下代码里的问题,主要是动态元素事件绑定失效、DOM定位错误和重复ID冲突这几个点导致了子级分类(比如Cat-1.1.1)没有显示在对应父级(Cat-1.1)下,反而出现父级被移除、子级错位的情况。下面是具体的解决方案:

关键问题分析

  1. 重复ID冲突:HTML和JS里多次使用id="video_search",ID是全局唯一的,重复使用会导致选择器无法精准定位目标元素。
  2. 动态元素事件绑定错误:直接给.category_child绑定click事件,但这个元素是AJAX请求后动态生成的,常规绑定无法生效。
  3. DOM插入逻辑混乱:生成子级HTML后没有精准插入到对应父级的category_nested容器,而是全局插入,导致结构错乱。

修改后的代码实现

1. 修正HTML代码(解决重复ID问题)

把所有id="video_search"改成class="video_search",并确保容器结构清晰:

<html>
<body>
<div class="content-body">
    <div class="row ">
        <div class="col-lg-12 col-md-12 col-12 ">
            <ul id="myUL" class="datatable-search-div" style="display: none;">
                <?php if (!empty($model)) { 
                    foreach ($model as $key => $value) { ?>
                    <li class="category_video">
                        <span class="caret">
                            <a href="<?= $value['uuid']; ?>" class="video_search" 
                               data-uuid="<?= $value['uuid']; ?>" 
                               data-parentid="<?= $value['parent_id']; ?>" 
                               data-name="<?= $value['name']; ?>" 
                               data-toggle="tab" 
                               onclick="videoShow('<?= $value['uuid']; ?>');">
                                <?= $value['name']; ?>
                            </a>
                        </span>
                        <ul class="nested" data-id="<?= $value['uuid']; ?>" id="tab_<?= $value['uuid']; ?>" 
                            role="tablist" style="display:none;">
                            <li class="category_child" data-id="<?= $value['uuid']; ?>">
                                <ul class="category_nested" id="nested_<?= $value['uuid']; ?>" role="tablist"></ul>
                            </li>
                        </ul>
                    </li>
                <?php } } ?>
            </ul>
        </div>
    </div>
</div>
<div class="tab-content float-left vertical col-xl-12 col-lg-12 col-md-3 col-3 left-aligned" 
     id="myTabContent5" style="display:none;">
    <?php if (!empty($model)) { ?>
        <div id="content_<?= $value['uuid']; ?>" class="tab-pane showVideo fade active show"></div>
    <?php } ?>
</div>
</body>
</html>

2. 修正注册JS代码(修复事件绑定和DOM插入逻辑)

$this->registerJs( '
function videoShow(id){
    var url = "' . Url::to(['test/get-videos-from-category']) . '?id="+id;
    $.ajax({
        type: "GET",
        url: url,
        beforeSend: function() { blockBody(); },
        success:function(data){
            unblockBody();
            $("#myTabContent5").show();
            $(".showVideo").html(data);
            
            // 解析返回的分类数据(从hidden元素中提取)
            var categoryNodes = [];
            $(data).find(".hidden").each(function(){
                categoryNodes.push({
                    name: $(this).find(".category_name").text(),
                    uuid: $(this).find(".category_uuid").text(),
                    parentId: $(this).find(".category_parent_id").text()
                });
            });
            
            // 找到当前点击的父级容器(根据传入的id)
            var parentNestedContainer = $("#nested_" + id);
            if(parentNestedContainer.length === 0) return;
            
            // 生成子级HTML并插入到对应父容器
            var childHtml = "";
            categoryNodes.forEach(function(node){
                childHtml += `<li class="category_child" data-id="${node.uuid}">`;
                childHtml += `<a href="${node.uuid}" class="video_search" data-uuid="${node.uuid}" data-parentid="${node.parentId}" data-name="${node.name}" data-toggle="tab" onclick="videoShow(\'${node.uuid}\');" style="margin-left: 20px;">${node.name}</a>`;
                childHtml += `<ul class="category_nested" id="nested_${node.uuid}" role="tablist"></ul>`;
                childHtml += `</li>`;
            });
            
            parentNestedContainer.html(childHtml);
            
            // 处理展开/收起样式
            $(`#tab_${id}`).show();
            $(`#tab_${id}`).closest(".category_video").find(".caret").addClass("caret-down");
        },
        error:function(e){
            unblockBody();
            showErrorMessage(e.responseText);
        }
    });
}

// 用事件委托处理动态生成的.caret点击事件(展开/收起)
$(document).on("click", ".caret", function(e){
    e.preventDefault();
    var $this = $(this);
    var $siblingNested = $this.next(".nested");
    
    // 切换展开/收起状态
    $siblingNested.toggle();
    $this.toggleClass("caret-down");
    
    // 关闭其他同级展开的节点
    $this.closest(".category_video").siblings().find(".nested").hide();
    $this.closest(".category_video").siblings().find(".caret").removeClass("caret-down");
});
', View::POS_END );

关键改动说明

  • 唯一ID命名:把容器ID改成tab_xxx和nested_xxx的格式,确保每个节点的ID唯一,避免选择器冲突。
  • 事件委托:用$(document).on("click", ".caret", ...)处理动态元素的点击事件,确保新生成的节点也能触发展开/收起逻辑。
  • 精准DOM插入:根据传入的父级ID找到对应的category_nested容器,把生成的子级HTML直接插入到该容器中,保证子级属于正确的父节点。
  • 简化逻辑:去掉了原JS中冗余的重复赋值和混乱的DOM操作,让代码逻辑更清晰。

内容的提问来源于stack exchange,提问作者Akash Shrimali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:42:26