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

如何通过wp_nav_menu的items_wrap参数修改菜单HTML结构?

解决方案:结合items_wrap和自定义Walker实现

嘿,这个需求我刚好处理过,咱们一步步来拆解:直接用items_wrap参数可以移除外层的<ul>,但要把父级<li>转成<div>,就得配合自定义的Walker_Nav_Menu类了——wp_nav_menu自带的参数没法直接改菜单项的标签,得靠Walker来定制输出结构。

第一步:移除外层<ul>

默认的items_wrap参数是 <ul id="%1$s" class="%2$s">%3$s</ul>,其中%3$s是所有菜单项的内容。你只需要把它改成%3$s,就能去掉外层的<ul>容器:

wp_nav_menu(array(
    'theme_location' => 'your-menu-location', // 替换成你的菜单位置
    'items_wrap'     => '%3$s',
));

第二步:把父级菜单项转成<div>

要实现父项从<li>变<div>,我们需要自定义一个Walker类,继承默认的Walker_Nav_Menu,重写start_el和end_el方法,判断当前菜单项是否是父级(带子菜单),然后切换标签:

class Custom_Menu_Walker extends Walker_Nav_Menu {
    // 处理菜单项的开始标签
    function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
        // 判断当前项是否是带子菜单的父项
        $is_parent = in_array('menu-item-has-children', $item->classes);
        // 父项用<div>,子项保持<li>
        $tag = $is_parent ? 'div' : 'li';

        // 处理菜单项的类名和ID(保留WordPress默认的过滤逻辑)
        $classes = array_filter((array)$item->classes);
        $classes[] = 'menu-item-' . $item->ID;
        $class_names = join(' ', apply_filters('nav_menu_css_class', $classes, $item, $args, $depth));
        $class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';

        $id = apply_filters('nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args, $depth);
        $id = $id ? ' id="' . esc_attr($id) . '"' : '';

        // 拼接开始标签
        $output .= '<' . $tag . $id . $class_names . '>';

        // 处理菜单项的链接和标题(保留默认逻辑)
        $atts = array(
            'title'  => $item->attr_title,
            'target' => $item->target,
            'rel'    => $item->xfn,
            'href'   => $item->url,
        );
        $atts = apply_filters('nav_menu_link_attributes', $atts, $item, $args, $depth);
        $attributes = '';
        foreach ($atts as $attr => $value) {
            if (!empty($value)) {
                $value = ($attr === 'href') ? esc_url($value) : esc_attr($value);
                $attributes .= " $attr=\"$value\"";
            }
        }

        $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);
    }

    // 处理菜单项的结束标签,和开始标签对应
    function end_el(&$output, $item, $depth = 0, $args = null) {
        $is_parent = in_array('menu-item-has-children', $item->classes);
        $tag = $is_parent ? 'div' : 'li';
        $output .= "</$tag>\n";
    }
}

第三步:组合调用

把上面的Walker类放到你的主题functions.php里,然后调用wp_nav_menu时指定这个Walker:

wp_nav_menu(array(
    'theme_location' => 'your-menu-location', // 替换成你的菜单位置
    'items_wrap'     => '%3$s', // 移除外层<ul>
    'walker'         => new Custom_Menu_Walker(), // 使用自定义Walker
));

额外说明

  • WordPress会自动给带子菜单的菜单项添加menu-item-has-children类,所以我们靠这个类来区分父项和子项。
  • 如果需要调整子菜单的外层容器(比如把<ul>改成<div>),可以重写Walker的start_lvl和end_lvl方法来实现。
  • 测试的时候记得清空缓存,避免旧的菜单结构影响结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:24:42