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

WooCommerce:生成父子分类嵌套UL层级及展开收起功能求助

解决WooCommerce分类嵌套层级与展开收起交互问题

问题说明

需要实现嵌套的ul/li分类结构:

  • 子分类需嵌套在对应父分类下
  • 父分类点击仅展开/收起子分类,不加载产品
  • 子分类点击加载对应产品

目前已成功获取分类数据,链接加载产品功能正常,但所有分类平级显示,无法形成嵌套层级。

现有前端代码

function loadProductCategoriesAndGenerateLinks() {
// Show the loading spinner
$("#loading-spinner2").show();

$.ajax({
  url: twentytwentyone_ajax_object.ajax_url,
  type: 'POST',
  dataType: 'json',
  data: {
    action: 'get_product_categories',
  },
  success: function(response) {
    if (response && response.categories) {
      var categories = response.categories;
      var treeContainer = $("#category-tree");
      treeContainer.empty();

      // Recursive function to generate the category tree
      function generateCategoryTree(categories, parentElement) {
        var ul = $('<ul>');
        $.each(categories, function(index, category) {
          var li = $('<li>');
          var link = $('<a>')
            .addClass('load-category-products')
            .attr('href', '#')
            .attr('data-category', category.slug)
            .text(category.name);
          li.append(link);

          if (category.children && category.children.length > 0) {
            // If the category has children, recursively generate their tree
            generateCategoryTree(category.children, li);
          }

          ul.append(li);
        });

        parentElement.append(ul); // Append the generated <ul> with <li> elements to the parent <li>
      }

      // Start generating the category tree from the top-level categories
      generateCategoryTree(categories, treeContainer);

      // Hide the loading spinner after the category tree is generated
      $("#loading-spinner2").hide();
    }
  },
  error: function(error) {
    // Handle error if necessary
    // Hide the loading spinner in case of an error
    $("#loading-spinner2").hide();
  }
});
}

当前生成的错误结构

<ul>
   <li><a>Link to Subcategory 1</a></li>
   <li><a>Link to Subcategory 2</a></li>
   <li><a>Link to Subcategory 3</a></li>
   <li><a>Link to Subcategory 4</a></li>
   <li><a>Link to Parent category 1 (for example of Subcategory 3 and 4)</a></li>
   <li><a>Link to Subcategory 5</a></li>
</ul>

解决方案

1. 后端调整:返回树形结构分类数据

WooCommerce默认获取的分类是平级的,需要在PHP接口中递归整理出父子嵌套结构:

function get_product_categories() {
    // 获取顶级分类(parent=0)
    $categories = get_terms(array(
        'taxonomy' => 'product_cat',
        'hide_empty' => false,
        'parent' => 0
    ));

    // 递归添加子分类到父分类的children属性
    function add_child_categories(&$categories) {
        foreach ($categories as &$category) {
            $children = get_terms(array(
                'taxonomy' => 'product_cat',
                'hide_empty' => false,
                'parent' => $category->term_id
            ));
            if (!empty($children)) {
                $category->children = $children;
                add_child_categories($category->children);
            }
        }
    }

    add_child_categories($categories);
    wp_send_json_success(array('categories' => $categories));
}
add_action('wp_ajax_get_product_categories', 'get_product_categories');
add_action('wp_ajax_nopriv_get_product_categories', 'get_product_categories');

2. 前端调整:生成嵌套结构并添加展开收起逻辑

修改前端代码,区分父/子分类交互,实现展开收起:

function loadProductCategoriesAndGenerateLinks() {
    $("#loading-spinner2").show();

    $.ajax({
        url: twentytwentyone_ajax_object.ajax_url,
        type: 'POST',
        dataType: 'json',
        data: { action: 'get_product_categories' },
        success: function(response) {
            if (response?.data?.categories) {
                const categories = response.data.categories;
                const treeContainer = $("#category-tree");
                treeContainer.empty();

                function generateCategoryTree(categories, parentElement) {
                    const ul = $('<ul>');
                    $.each(categories, (index, category) => {
                        const li = $('<li>');
                        const link = $('<a>')
                            .addClass('load-category-products')
                            .attr('href', '#')
                            .attr('data-category', category.slug)
                            .text(category.name);

                        // 处理有子分类的父分类
                        if (category.children?.length > 0) {
                            // 添加展开收起按钮
                            const toggleBtn = $('<span>')
                                .addClass('category-toggle')
                                .text('+');
                            li.prepend(toggleBtn);

                            // 阻止父分类链接默认行为,点击链接触发展开收起
                            link.on('click', e => {
                                e.preventDefault();
                                toggleBtn.trigger('click');
                            });

                            // 展开收起事件逻辑
                            toggleBtn.on('click', () => {
                                const childUl = li.find('ul:first');
                                if (childUl.is(':visible')) {
                                    childUl.hide();
                                    toggleBtn.text('+');
                                } else {
                                    childUl.show();
                                    toggleBtn.text('-');
                                }
                            });

                            // 生成子分类列表并默认隐藏
                            const childUl = $('<ul>').hide();
                            generateCategoryTree(category.children, childUl);
                            li.append(childUl);
                        }

                        li.append(link);
                        ul.append(li);
                    });
                    parentElement.append(ul);
                }

                generateCategoryTree(categories, treeContainer);
                $("#loading-spinner2").hide();
            }
        },
        error: () => $("#loading-spinner2").hide()
    });
}

3. 添加基础样式优化显示

.category-toggle {
    display: inline-block;
    width: 18px;
    height: 18px;
    line-height: 18px;
    text-align: center;
    cursor: pointer;
    margin-right: 8px;
    font-weight: bold;
    user-select: none;
}

#category-tree ul {
    margin-left: 24px;
    padding-left: 0;
    list-style: none;
}

#category-tree li {
    margin: 4px 0;
}

说明

  • 后端通过get_terms先获取顶级分类,再递归获取每个分类的子分类,确保返回的数据是树形结构
  • 前端针对有子分类的父分类添加展开收起按钮,阻止其链接的产品加载行为,仅处理展开收起
  • 子分类列表默认隐藏,点击父分类按钮或链接切换显示状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:02:21