求助:制作适配Bootstrap 4手风琴的WordPress垂直侧边栏Walker类
我明白你想要实现的Bootstrap手风琴侧边栏菜单结构,你的现有代码主要问题在于没有动态生成手风琴所需的关联ID和ARIA属性,还有一些语法错误和类名不匹配的问题。下面我会帮你重构这个Walker类,完全匹配你需要的HTML结构:
修正后的完整Walker类代码
<?php class Walker_Indice extends Walker_Nav_Menu { // 存储当前折叠菜单的ID,用于关联父链接和子菜单 private $current_collapse_id; public function start_lvl( &$output, $depth = 0, $args = array() ) { $indent = str_repeat("\t", $depth); // 手风琴父容器的ID(要和wp_nav_menu设置的container_id对应) $parent_container_id = '#sidebarIndice'; // 关联的heading ID(从collapse ID反向生成) $aria_labelledby = str_replace('indicecollapse-', 'indiceheading-', $this->current_collapse_id); // 判断是否需要默认展开:如果当前项或父项是活跃状态,添加show类 $show_class = (in_array('current-menu-item', $args->current_item_classes) || in_array('current-menu-ancestor', $args->current_item_classes)) ? ' show' : ''; // 生成正确的子菜单ul标签 $output .= "\n$indent<ul id=\"" . esc_attr($this->current_collapse_id) . "\" class=\"collapse$show_class\" aria-labelledby=\"" . esc_attr($aria_labelledby) . "\" data-parent=\"" . esc_attr($parent_container_id) . "\">\n"; } public function end_lvl( &$output, $depth = 0, $args = array() ) { $indent = str_repeat("\t", $depth); $output .= "$indent</ul>\n"; } public function start_el(&$output, $item, $depth=0, $args=array(), $id=0){ $indent = ($depth) ? str_repeat("\t", $depth) : ''; $li_attributes = ''; $class_names = $value = ''; // 处理菜单项的class $classes = empty( $item->classes ) ? array() : (array) $item->classes; $classes[] = ($item->current || $item->current_item_ancestor) ? 'active' : ''; $classes[] = 'menu-item-' . $item->ID; $class_names = join(' ', apply_filters('nav_menu_css_class', array_filter( $classes ), $item, $args)); $class_names = ' class="' . esc_attr($class_names) . '"'; // 处理菜单项的ID $id = apply_filters('nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args); $id = strlen( $id ) ? ' id="' . esc_attr( $id ) . '"' : ''; // 开始生成li标签 $output .= $indent . '<li' . $id . $value . $class_names . $li_attributes . '>'; // 处理链接的属性 $attributes = ! empty( $item->attr_title ) ? ' title="' . esc_attr($item->attr_title) . '"' : ''; $attributes .= ! empty( $item->target ) ? ' target="' . esc_attr($item->target) . '"' : ''; $attributes .= ! empty( $item->xfn ) ? ' rel="' . esc_attr($item->xfn) . '"' : ''; $attributes .= ! empty( $item->url ) ? ' href="' . esc_attr($item->url) . '"' : ''; // 如果当前菜单项有子菜单,生成手风琴所需的特殊属性 if($args->walker->has_children) { // 生成唯一的ID对:heading和collapse $heading_id = 'indiceheading-' . $item->ID; $this->current_collapse_id = 'indicecollapse-' . $item->ID; // 判断是否展开:活跃状态则展开,否则折叠 $is_expanded = (in_array('current-menu-item', $classes) || in_array('current-menu-ancestor', $classes)) ? 'true' : 'false'; $collapsed_class = ($is_expanded === 'false') ? ' collapsed' : ''; // 添加手风琴相关属性 $attributes .= ' id="' . esc_attr($heading_id) . '"'; $attributes .= ' data-toggle="collapse"'; $attributes .= ' data-target="#' . esc_attr($this->current_collapse_id) . '"'; $attributes .= ' aria-expanded="' . esc_attr($is_expanded) . '"'; $attributes .= ' aria-controls="' . esc_attr($this->current_collapse_id) . '"'; $attributes .= ' class="custom-class' . $collapsed_class . '"'; } else { // 没有子菜单的普通链接,用你需要的类(如果需要自定义可以修改) $attributes .= ' class="custom-class"'; } // 生成链接的内容 $item_output = $args->before; $item_output .= '<a' . $attributes . '>'; $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after; $item_output .= '</a>'; // 修复原代码漏掉的闭合标签 $item_output .= $args->after; $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args ); } }
关键修改说明
- 添加类属性
$current_collapse_id:用于在处理子菜单时,关联父链接生成的唯一ID,保证手风琴的点击关联正确。 - 动态生成唯一ID对:每个有子菜单的父项都会生成
indiceheading-{菜单项ID}和indicecollapse-{菜单项ID}的ID,避免冲突。 - 处理ARIA属性和折叠状态:根据菜单项是否为当前活跃项(或父项活跃),自动设置
aria-expanded和collapsed类,默认展开活跃菜单。 - 修正start_lvl的语法错误:之前的代码错误地写了
ul=\"collapse deph_$depth\",现在生成符合Bootstrap要求的折叠菜单容器,包含data-parent关联手风琴父容器。 - 修复链接闭合问题:原代码漏掉了
</a>闭合标签,这会导致HTML结构混乱,现已补上。
如何调用这个Walker
在你的主题模板(比如sidebar.php)中,用以下代码调用菜单:
wp_nav_menu(array( 'theme_location' => 'your-sidebar-menu-slug', // 替换成你在后台设置的菜单位置 'walker' => new Walker_Indice(), 'container' => 'div', 'container_id' => 'accordion', // 对应你要的外层div#accordion 'menu_id' => 'sidebarIndice', // 对应子菜单的data-parent="#sidebarIndice" 'menu_class' => '', // 去掉默认的menu类,保持你需要的结构 ));
额外提示
如果你需要手动强制某个菜单默认展开,不需要依赖活跃状态,可以在WordPress后台的菜单编辑页面,给父菜单项添加自定义classforce-expand,然后在start_el方法中修改$is_expanded的判断逻辑:
$is_expanded = (in_array('force-expand', $classes) || in_array('current-menu-item', $classes) || in_array('current-menu-ancestor', $classes)) ? 'true' : 'false';
内容的提问来源于stack exchange,提问作者ilfedevisio
相关产品推荐
相关产品推荐

