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
相关产品推荐
相关产品推荐

