WordPress 设置菜单

一,WordPress 使用 register_nav_menus() 设置菜单位置

导航菜单注册函数 register_nav_menus()
在主题的 functions.php 中添加:

if (function_exists('register_nav_menus')) {
    register_nav_menus(array(
        'header_main' => __('顶部菜单'),
        'footer_bottom' => __('底部菜单')
    )); 
}

上面注册了两个菜单位置,其中 ‘header_main’ 和 ‘footer_bottom’ 分别是这两个菜单的“键key”,后面的值是菜单的标题,会在 “外观->菜单->管理位置” 显示出来。

 

二,使用 wp_nav_menu() 生成菜单

使用的时候,指定菜单名称即可:

$nav_str = wp_nav_menu( array(  
    'theme_location'    => 'footer_bottom', //[保留]用于在调用导航菜单时指定注册过的某一个导航菜单名,如果没有指定,则显示第一个  
    'menu'              => 'footer_bottom', //[可删]使用导航菜单的名称调用菜单,可以是 id, slug, name (按顺序匹配的) 。  
    'container'         => false, //[可删]最外层容器标签名  
    'container_class'   => '',//[可删]最外层容器class名  
    'container_id'      => '',//[可删]最外层容器id值  
    'menu_class'        => 'footer-link-container', //[可删]ul 节点的 class 属性值  
    'menu_id'           => '', //[可删]ul 节点的 id 属性值  
    'echo'              => false, //[可删]确定直接显示导航菜单还是返回 HTML 片段,如果想将导航的代码作为赋值使用,可设置为false  
    'fallback_cb'       => 'wp_page_menu', //[可删]备用的导航菜单函数,用于没有在后台设置导航时调用  
    'before'            => '', //[可删]显示在导航a标签之前  
    'after'             => '', //[可删]显示在导航a标签之后    
    'link_before'       => '', //[可删]显示在导航链接名之前  
    'link_after'        => '', //[可删]显示在导航链接名之后  
    'items_wrap'        => '<ul id="%1$s" class="%2$s">%3$s</ul>',  //[可删]使用字符串替换修改ul的class  
    'depth'             => 0, //[可删]显示菜单的深度, 当数值为0时显示所有深度的菜单,-1所有菜单平级显示  
    'walker'            => '' //[可删]自定义的遍历对象,调用一个对象定义显示导航菜单      
));

echo str_replace('sub-menu', 'select', $nav_str);

三,使用 Walker_Nav_Menu 类创建自定义分类

3.1. Walker_Nav_Menu 基础
什么是 Walker 类?
Walker 是一个抽象类,用于”遍历”树状结构数据并生成 HTML。Walker_Nav_Menu 是专门用于导航菜单的子类。

为什么要使用它?
完全控制菜单的 HTML 结构

添加自定义 CSS 类或数据属性

创建复杂的菜单布局(如 mega menu)

在菜单项前后添加额外内容(如图标)

3.2. 基本使用方法
WordPress Walker_Nav_Menu 教程:自定义导航菜单
Walker_Nav_Menu 是 WordPress 的一个核心类,允许开发者完全自定义导航菜单的 HTML 输出结构。本教程将带你全面了解如何使用它。

  1. Walker_Nav_Menu 基础
    什么是 Walker 类?
    Walker 是一个抽象类,用于”遍历”树状结构数据并生成 HTML。Walker_Nav_Menu 是专门用于导航菜单的子类。

为什么要使用它?
完全控制菜单的 HTML 结构

添加自定义 CSS 类或数据属性

创建复杂的菜单布局(如 mega menu)

在菜单项前后添加额外内容(如图标)

  1. 基本使用方法
    创建自定义 Walker 类
class My_Custom_Walker extends Walker_Nav_Menu {
    // 这里添加方法覆盖
}

在主题中调用

wp_nav_menu(array(
    'theme_location' => 'primary',
    'walker' => new My_Custom_Walker(),
));
  1. 核心方法详解
    start_lvl() – 开始子菜单
function start_lvl(&$output, $depth = 0, $args = null) {
    $indent = str_repeat("\t", $depth);
    $output .= "\n{$indent}<ul class=\"sub-menu depth-{$depth}\">\n";
}

end_lvl() – 结束子菜单

function end_lvl(&$output, $depth = 0, $args = null) {
    $indent = str_repeat("\t", $depth);
    $output .= "{$indent}</ul>\n";
}

start_el() – 开始菜单项

function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
    $indent = ($depth) ? str_repeat("\t", $depth) : '';
    
    $classes = empty($item->classes) ? array() : (array) $item->classes;
    $classes[] = 'menu-item-' . $item->ID;
    
    $output .= $indent . '<li id="menu-item-'. $item->ID . '" class="' . implode(' ', $classes) . '">';
    
    $atts = array();
    $atts['title']  = !empty($item->attr_title) ? $item->attr_title : '';
    $atts['target'] = !empty($item->target)     ? $item->target     : '';
    $atts['rel']    = !empty($item->xfn)        ? $item->xfn        : '';
    $atts['href']   = !empty($item->url)        ? $item->url        : '';
    
    $attributes = '';
    foreach ($atts as $attr => $value) {
        if (!empty($value)) {
            $attributes .= ' ' . $attr . '="' . esc_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);
}

end_el() – 结束菜单项

function end_el(&$output, $item, $depth = 0, $args = null) {
    $output .= "</li>\n";
}
  1. 实用案例
    案例1:添加图标
function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
    // ...前面的代码...
    
    // 获取存储在菜单项的图标类名
    $icon_class = get_post_meta($item->ID, '_menu_item_icon', true);
    $icon = $icon_class ? '<i class="' . esc_attr($icon_class) . '"></i> ' : '';
    
    $item_output = $args->before;
    $item_output .= '<a'. $attributes .'>';
    $item_output .= $icon; // 添加图标
    $item_output .= $args->link_before . apply_filters('the_title', $item->title, $item->ID) . $args->link_after;
    $item_output .= '</a>';
    $item_output .= $args->after;
    
    // ...后面的代码...
}

案例2:创建 Mega Menu

function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
    // ...基本代码...
    
    // 检查是否是mega menu
    $is_mega = get_post_meta($item->ID, '_menu_item_mega', true);
    
    if ($depth === 0 && $is_mega) {
        $classes[] = 'mega-menu';
    }
    
    // ...继续渲染...
}

function end_el(&$output, $item, $depth = 0, $args = null) {
    $is_mega = get_post_meta($item->ID, '_menu_item_mega', true);
    
    if ($depth === 0 && $is_mega) {
        // 添加mega menu内容
        $mega_content = get_post_meta($item->ID, '_menu_item_mega_content', true);
        if ($mega_content) {
            $output .= '<div class="mega-menu-content">' . apply_filters('the_content', $mega_content) . '</div>';
        }
    }
    
    $output .= "</li>\n";
}
  1. 高级技巧
    添加自定义字段
    首先在菜单项中添加字段:
add_action('wp_nav_menu_item_custom_fields', function($item_id, $item, $depth, $args) {
    $icon = get_post_meta($item_id, '_menu_item_icon', true);
    ?>
    <p class="field-icon description description-wide">
        <label>
            图标类名<br>
            <input type="text" name="menu-item-icon[<?php echo $item_id; ?>]" value="<?php echo esc_attr($icon); ?>">
        </label>
    </p>
    <?php
}, 10, 4);

保存字段:

add_action('wp_update_nav_menu_item', function($menu_id, $menu_item_db_id, $args) {
    if (isset($_POST['menu-item-icon'][$menu_item_db_id])) {
        update_post_meta($menu_item_db_id, '_menu_item_icon', sanitize_text_field($_POST['menu-item-icon'][$menu_item_db_id]));
    }
}, 10, 3);

性能优化
对于大型菜单,考虑缓存输出:

function wp_nav_menu_cached($args = array()) {
    $menu = wp_get_nav_menu_object($args['menu']);
    
    if (!$menu) return '';
    
    $transient_key = 'nav_menu_' . $menu->term_id;
    $cached = get_transient($transient_key);
    
    if ($cached !== false) {
        return $cached;
    }
    
    ob_start();
    wp_nav_menu($args);
    $menu_content = ob_get_clean();
    
    set_transient($transient_key, $menu_content, DAY_IN_SECONDS);
    
    return $menu_content;
}
  1. 常见问题解答
    Q: 如何只对特定菜单使用 Walker?
    A: 在调用 wp_nav_menu() 时通过 theme_location 判断:
$walker = ('primary' === $args['theme_location']) ? new My_Custom_Walker() : new Walker_Nav_Menu();
wp_nav_menu(array('theme_location' => 'primary', 'walker' => $walker));

Q: 如何添加当前菜单项的额外类?
A: 在 start_el() 方法中修改 $classes 数组:

if (in_array('current-menu-item', $classes)) {
    $classes[] = 'active';
}

Q: 如何限制菜单深度?
A: 使用 max_depth 参数:

wp_nav_menu(array(
    'theme_location' => 'primary',
    'walker' => new My_Custom_Walker(),
    'depth' => 2 // 只显示2级菜单
));

通过掌握 Walker_Nav_Menu,你可以完全控制 WordPress 菜单的输出,实现各种复杂的导航需求。

 

收藏
评论
打赏
WordPress 分类添加自定义字段
上一篇
搜索引擎提交入口
下一篇
像素鱼丸
47395 阅读
87 发布
3 收藏
动态
MirageV 主题 2.14.0 发布
MirageV 主题 2.16.2 发布
MirageV 主题 v2.6.4 发布
FishV 主题 v1.14 发布
LandV 企业主题 v2.6.0 发布
BotV 插件 v1.7.0 发布
MirageV 主题 v2.5 正式发布
FishV 主题 v1.21.0 发布
生成中...
真诚赞赏,手留余香
登录
注册
重置密码