WordPress开发笔记

WordPress经典主题导航wp_nav_menu()函数调用示例及参数详解

函数wp_nav_menu()详解部分

wp_nav_menu( array $args = array() ): void|string|false

显示导航菜单。

本文大多摘自WordPress官方网站。

此外,我还整理了很多来自AI(deepseek)以及我个人创作的实现的代码。

wp_nav_menu() 是WordPress中用于显示导航菜单的核心函数。通过灵活配置其参数,我们可以完全控制菜单的输出结构。以下是其核心参数详解:

<?php
$zzw_defaults = array(
    ‘theme_location’  => '',      // 在主题中注册的菜单位置标识符
    ‘menu’            => '',      // 期望显示的菜单ID、slug、名称
    ‘container’       => 'div',   // 菜单最外层容器标签,设置为false则不显示容器
    ‘container_class’ => '',      // 外层容器的class
    ‘container_id’    => '',      // 外层容器的id
    ‘menu_class’      => 'menu',  // 菜单ul元素的class
    ‘menu_id’         => '',      // 菜单ul元素的id
    ‘echo’            => true,    // 是否直接显示菜单,false则返回菜单HTML字符串
    ‘fallback_cb’     => 'wp_page_menu', // 当菜单不存在时的回调函数
    ‘before’          => '',      // 每个菜单链接文本前的HTML
    ‘after’           => '',      // 每个菜单链接文本后的HTML
    ‘link_before’     => '',      // 每个菜单链接文本前的HTML
    ‘link_after’      => '',      // 每个菜单链接文本后的HTML
    ‘items_wrap’      => '<ul id="%1$s" class="%2$s">%3$s</ul>', // 菜单项包裹格式
    ‘item_spacing’    => 'preserve', // 是否保留HTML空白,'discard'可去除
    ‘depth’           => 0,       // 菜单层级深度,0为所有,1为一层
    ‘walker’          => ''       // 自定义遍历器对象,用于完全自定义输出结构
);
wp_nav_menu( $zzw_defaults );
?>

参数

$args 数组 自选

导航菜单参数的阵列。

  • menu  int|string|WP_Term
    想要的菜单。接受菜单ID、slug、名称或对象。
    该参数依赖于 WordPress 管理面板创建菜单时分配的名称。因此,建议将参数值与创建菜单时给定的名称匹配。
    此处的具体输入值应该是什么?详见:
    WordPress菜单名称 WordPress菜单名称2
  • menu_class 字符串
    用于ul元素的CSS类,ul元素构成菜单。默认为'menu'。你可以输入你的自定义名称。
  • menu_id 字符串
    应用到构成菜单的ul元素上的ID。默认是菜单的slug,按比例递增。
  • container 字符串
    是否要包裹UL,以及用什么包裹。默认为'div'
    container容器参数默认只接受“div”、“nav”和虚假值(“, false, null”);
    如果你想扩展被接受的标签参数,并且用别的东西包裹菜单上的父 ul 标签,你必须用wp_nav_menu_container_allowedtags过滤器,把想要的标签添加到数组里。然而,对于大多数用途来说,默认的两个标签是最合理的。
    为虚假值时,意味着移除该容器,输入将仅保留ul元素部分。

  • container_class 字符串
    应用于容器的类别。默认为“menu-{menu slug}-container。
  • container_id 字符串
    应用到容器上的ID。
  • container_aria_label 字符串
    当容器是导航元素时应用的 aria 标签属性。
  • fallback_cb 可调用|false
    如果菜单不存在,回调函数会触发。默认是。设置为false,没有备选方案。'wp_page_menu'
  • before 字符串
    链接标记前的文字。
  • after 字符串
    链接标记后再发短信。
  • link_before 字符串
    在链接前先写文字。
  • link_after 字符串|
    链接后再加文字。
  • echo 布尔
    是跟菜单呼应还是退回菜单。默认是true。
  • depth 智力
    包含多少层级的层级。0 表示全部。默认为0。默认为0。
  • walker 对象
    自定义步行机类的实例。
  • theme_location 字符串
    主题位置将被使用。必须注册为 register_nav_menu(),用户才能选择。
    使用“theme_location”参数,显示该位置附加或选择的菜单。该位置必须事先在functions.php文件中注册该功能。
  • items_wrap 字符串
    清单项目应该如何包装。使用带有编号占位符的 printf() 格式。默认是带有id和class的ul。
  • item_spacing 字符串
    是否要在菜单的 HTML 中保留空白。接受或 。违约。'preserve''discard''preserve'

违约:array()

函数用法

wp_nav_menu( $args );

给定一个theme_location参数,函数会显示分配给该位置的菜单。如果没有这样的位置或没有分配菜单,参数fallback_cb将决定显示的内容。

如果没有给出theme_location参数,函数会显示

  • 菜单中与菜单参数给出的ID、字块或名称相匹配;
  • 否则,第一个非空菜单;
  • 否则(或菜单给出的菜单为空),输出由fallback_cb参数给出的函数(默认为wp_page_menu());
  • 否则什么都没有。

以下类应用于导航菜单项,即由 HTML <li> 标签生成:wp_nav_menu()

所有导航菜单项

  • .menu-item
    这个职业会被添加到每一项菜单中。
  • .menu-item-has-children
    该类被添加到菜单项中,菜单项包含子项。
  • .menu-item-object-{object}
    该类被添加到每个菜单项中,其中 {object} 是帖子类型或分类法。
  • .menu-item-object-category
    该类被添加到对应类别的菜单项中。
  • .menu-item-object-tag
    该类被添加到对应标签的菜单项中。
  • .menu-item-object-page
    该类被添加到对应静态页面的菜单项中。
  • .menu-item-object-{custom}
    该类被添加到对应自定义帖子类型或自定义分类法的菜单项中。
  • .menu-item-type-{type}
    该类被添加到每个菜单项中,其中 {type} 是“post_type”或“taxonomy”。
  • .menu-item-type-post_type
    该类被添加到对应帖子类型的菜单项中,即静态页面或自定义帖子类型。
  • .menu-item-type-taxonomy
    该类被添加到对应分类法的菜单项中,即类别、标签或自定义分类法。

当前页面导航菜单项

  • .current-menu-item
    该类被添加到对应当前渲染页面的菜单项中。

当前页面父菜单项

  • .current-menu-parent
    该类被添加到对应当前渲染页面的层级父菜单项中。
  • .current-{object}-parent
    该类被添加到对应当前渲染对象层级父的菜单项中,其中 {object} 对应于 .menu-item-object-{object} 的值。
  • .current-{type}-parent
    该类被添加到对应当前渲染类型层级父的菜单项中,其中 {type} 对应于 .menu-item-type-{type} 的值。

当前页面祖先菜单项

  • .current-menu-ancestor
    该类被添加到对应当前渲染页面的层级祖先的菜单项中。
  • .current-{object}-ancestor
    该类被添加到对应当前渲染对象的层级祖先的菜单项中,其中 {object} 对应于 .menu-item-object-{object} 所使用的值。
  • .current-{type}-ancestor
    该类被添加到对应当前渲染类型层级祖先的菜单项中,其中 {type} 对应于 .menu-item-type-{type} 所使用的值。

网站首页导航菜单项目

  • .menu-item-home
    该类别被添加到对应网站首页的菜单项中。

与wp_page_menu()的向后兼容

为了保持与 [[函数参考/wp_page_menu|wp_page_menu() ]] 函数输出:

  • .page_item
    该类被添加到对应静态页面的菜单项中。
  • .page_item_has_children
    这个类会被添加到带有子页面的菜单项中。
  • .page-item-$ID
    该类被添加到对应静态页面的菜单项中,其中$ID是静态页面ID。
  • .current_page_item
    该类被添加到对应当前静态页面的菜单项中。
  • .current_page_parent
    该类被添加到对应当前静态页面的层级父菜单项中。
  • .current_page_ancestor
    该类被添加到对应当前静态页面的层级祖先的菜单项中。

显示第一个非空导航菜单

[html]
<?php wp_nav_menu() ; ?>
[/html]

登录用户的不同导航菜单

wp_nav_menu( array(
	'theme_location' => is_user_logged_in() ? 'logged-in-menu' : 'logged-out-menu'
) );

拆除包膜ul

此示例将去除无序列表环绕列表项的作。用指定符替换包裹 HTML 会导致菜单项的 HTML 列表内容输出,因为 是%3$sitems_wrapsprintf()

items_wrap默认之前:

[html]
<ul id=“%1$s” class=“%2$s”>%3$s</ul>
[/html]

items_wrap之后:

[html]
%3$s
[/html]
wp_nav_menu( array( 'items_wrap' => '%3$s' ) );

还没有导航菜单?预载占位菜单

如果你刚安装了WordPress并激活了主题,可能还没有在外观>菜单中设置主菜单。在这些情况下,你可能想先展示自己的占位菜单,直到菜单设置好。

为此,可以使用备用回调函数。这样:

wp_nav_menu( array( 'fallback_cb' => 'custom_primary_menu_fallback', 'menu' => 'menu', 'container' => false, 'menu_id' => 'menu', 'menu_class'=>'', 'theme_location'=>'primary-menu' ) );

function custom_primary_menu_fallback() {
  ?>
  <ul id="menu"><li><a href="/">Home</a></li><li><a href="/wp-admin/nav-menus.php">Set primary menu</a></li></ul>
  <?php
}

在激活菜单项中添加class

.active添加到激活菜单项中:

add_filter('nav_menu_css_class' , 'special_nav_class' , 10 , 2);
function special_nav_class($classes, $item){
     if( in_array('current-menu-item', $classes) ){
             $classes[] = 'active ';
     }
     return $classes;
}

清除菜单项<li>的默认Class,并为激活菜单项添加自定义class名

// 清除菜单项<li>的默认Class,并为激活菜单项添加自定义class名'zzw-current'
add_filter( 'nav_menu_css_class', 'zzw_clear_nav_menu_item_class', 10, 4 );
function zzw_clear_nav_menu_item_class( $classes, $item, $args, $depth ) {
	$zzw_clean_classes = array(); // 创建一个空数组,用于存放我们想保留的class
	
	// 只保留必要的class,例如当前菜单项的标识
	if ( in_array( 'current-menu-item', $classes ) ) {
		$zzw_clean_classes[] = 'zzw-current';
	}
	// 如果有需要,可以在此添加其他条件的class
	
	return $zzw_clean_classes; // 返回清理后的class数组
}

清除菜单项<li>的ID属性

// 清除菜单项<li>的ID属性
add_filter( 'nav_menu_item_id', 'zzw_clear_nav_menu_item_id', 10, 4 );
function zzw_clear_nav_menu_item_id( $menu_id, $item, $args, $depth ) {
	return ''; // 直接返回空字符串
}

为导航菜单项添加父类

/**
 * Add a parent CSS class for nav menu items.
 *
 * @param array  $items The menu items, sorted by each menu item's menu order.
 * @return array (maybe) modified parent CSS class.
 */
function wpdocs_add_menu_parent_class( $items ) {
	$parents = array();

	// Collect menu items with parents.
	foreach ( $items as $item ) {
		if ( $item->menu_item_parent && $item->menu_item_parent > 0 ) {
			$parents[] = $item->menu_item_parent;
		}
	}

	// Add class.
	foreach ( $items as $item ) {
		if ( in_array( $item->ID, $parents ) ) {
			$item->classes[] = 'menu-parent-item';
		}
	}
	return $items;
}
add_filter( 'wp_nav_menu_objects', 'wpdocs_add_menu_parent_class' );

筛选导航菜单项类别名称,以精准操作

// adds useful menu-item class names
function your_theme_menu_item_class( $classes, $item ) {

  // Add slugs to menu-items
  if ( 'category' == $item->object ) {
    $category = get_category( $item->object_id );
    $classes[] = 'category-' . $category->slug;
  } elseif ( 'format' == $item->object ){
    $format = get_term($item->object_id);
    $classes[] = 'format-' . $format->slug;
  }
  return $classes;  
}

add_filter( 'nav_menu_css_class', 'your_theme_menu_item_class', 10, 2);

向导航菜单项添加条件类

这个例子可以让你根据你指定的条件,在导航菜单项中添加自定义类。别忘了更换条件。

/**
 * Filter the CSS class for a nav menu based on a condition.
 *
 * @param array  $classes The CSS classes that are applied to the menu item's <li> element.
 * @param object $item    The current menu item.
 * @return array (maybe) modified nav menu class.
 */
function wpdocs_special_nav_class( $classes, $item ) {
	if ( is_single() && 'Blog' == $item->title ) {
		// Notice you can change the conditional from is_single() and $item->title
		$classes[] = "special-class";
	}
	return $classes;
}
add_filter( 'nav_menu_css_class' , 'wpdocs_special_nav_class' , 10, 2 );

清除菜单<ul>和容器上的默认class,并只使用自定义名

// 清除菜单<ul>和容器上的默认class,并只使用自定义名
// 通过wp_nav_menu参数直接设置空的class和id
wp_nav_menu( array(
	‘theme_location’  => ‘zzw_primary_menu’,
	‘container’       => ‘nav’,
	‘container_class’ => ‘zzw-nav-container’, // 只使用我们自己的class
	‘container_id’    => ‘’,                  // 清空ID
	‘menu_class’      => ‘zzw-nav-list’,      // 只使用我们自己的class
	‘menu_id’         => ‘’,                  // 清空ID
	‘fallback_cb’     => false
) );

经典主题导航添加自定义class

在找找网的实际项目中,我们经常需要为菜单项添加自定义class,例如用于特殊样式或JavaScript交互。

方法一:通过后台菜单的“CSS类”字段
这是最简单的方法,直接在WordPress后台的“外观”->“菜单”中,开启“CSS类”选项并填写。

方法二:通过代码过滤器动态添加

<?php
// 为菜单项<li>添加自定义class
add_filter( ‘nav_menu_css_class’, ‘zzw_add_custom_menu_classes’, 10, 4 );
function zzw_add_custom_menu_classes( $classes, $item, $args, $depth ) {

    // 确保我们只对特定的菜单位置进行操作
    if ( $args->theme_location == ‘zzw_primary_menu’ ) {

        // 1. 为所有菜单项添加一个通用class
        $classes[] = ‘zzw-nav-item’;

        // 2. 根据菜单项标题添加class(适用于特殊样式)
        $zzw_item_title = sanitize_title( $item->title ); // 将标题转为slug形式
        $classes[] = ‘zzw-menu-’ . $zzw_item_title; // 例如:zzw-menu-about-us

        // 3. 根据深度(层级)添加class
        $classes[] = ‘zzw-menu-depth-’ . $depth;

        // 4. 为特定的父级菜单项添加标识class
        if ( $item->menu_item_parent == 0 ) {
            $classes[] = ‘zzw-top-level-item’;
        }
    }

    return $classes;
}

// 为菜单链接<a>添加自定义class
add_filter( ‘nav_menu_link_attributes’, ‘zzw_add_custom_link_classes’, 10, 4 );
function zzw_add_custom_link_classes( $atts, $item, $args, $depth ) {
    if ( $args->theme_location == ‘zzw_primary_menu’ ) {
        $atts[‘class’] = ‘zzw-nav-link’; // 为所有链接添加基础class

        // 如果是当前页面,添加高亮class
        if ( in_array( ‘current-menu-item’, $item->classes ) ) {
            $atts[‘class’] .= ‘ zzw-nav-link-active’;
        }
    }
    return $atts;
}
?>

调用菜单:

<?php
wp_nav_menu( array(
    ‘theme_location’  => ‘zzw_primary_menu’,
    ‘container’       => ‘nav’,
    ‘container_class’ => ‘zzw-nav-container’,
    ‘menu_class’      => ‘zzw-nav-list’,
) );
?>

输出结构示例:

<nav class=“zzw-nav-container”>
    <ul class=“zzw-nav-list”>
        <li class=“zzw-nav-item zzw-menu-home zzw-menu-depth-0 zzw-top-level-item zzw-current”>
            <a href=“https://www.zhaozhaowang.com/” class=“zzw-nav-link zzw-nav-link-active”>首页</a>
        </li>
        <li class=“zzw-nav-item zzw-menu-about-us zzw-menu-depth-0 zzw-top-level-item”>
            <a href=“/about” class=“zzw-nav-link”>关于找找网</a>
        </li>
    </ul>
</nav>

高阶示例1:基础自定义导航Walker

基础自定义导航Walker,适合标准WordPress主题

<?php
class Basic_Custom_Walker extends Walker_Nav_Menu {
    public function start_lvl(&$output, $depth = 0, $args = null) {
        $output .= '<ul class="sub-menu depth-' . $depth . '">';
    }

    public function end_lvl(&$output, $depth = 0, $args = null) {
        $output .= '</ul>';
    }

    public function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
        $classes = empty($item->classes) ? array() : (array) $item->classes;
        $classes[] = 'menu-item-' . $item->ID;
        $classes[] = 'depth-' . $depth;

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

        $class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($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 .= '<li' . $id . $class_names . '>';

        $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 : '';
        $atts['class'] = 'nav-link';

        $atts = apply_filters('nav_menu_link_attributes', $atts, $item, $args, $depth);

        $attributes = '';
        foreach ($atts as $attr => $value) {
            if (!empty($value)) {
                $value = ('href' === $attr) ? esc_url($value) : esc_attr($value);
                $attributes .= ' ' . $attr . '="' . $value . '"';
            }
        }

        $title = apply_filters('the_title', $item->title, $item->ID);

        $item_output = $args->before;
        $item_output .= '<a' . $attributes . '>';
        $item_output .= $args->link_before . $title . $args->link_after;

        if (in_array('menu-item-has-children', $classes)) {
            $item_output .= '<span class="dropdown-arrow">▼</span>';
        }

        $item_output .= '</a>';
        $item_output .= $args->after;

        $output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
    }

    public function end_el(&$output, $item, $depth = 0, $args = null) {
        $output .= '</li>';
    }
}

function display_basic_custom_nav() {
    wp_nav_menu(array(
        'theme_location' => 'primary',
        'menu_class' => 'main-navigation',
        'container' => 'nav',
        'container_class' => 'site-navigation',
        'container_id' => 'site-navigation',
        'fallback_cb' => false,
        'walker' => new Basic_Custom_Walker(),
        'items_wrap' => '<ul id="%1$s" class="%2$s">%3$s</ul>',
        'depth' => 3
    ));
}
?>

高阶示例2:使用walk方法手动构建Bootstrap导航

Bootstrap兼容导航,使用walk方法手动构建

<?php
class Bootstrap_Walker extends Walker_Nav_Menu {
    public function start_lvl(&$output, $depth = 0, $args = null) {
        $dropdown_class = ($depth === 0) ? 'dropdown-menu' : 'dropdown-submenu';
        $output .= '<ul class="' . $dropdown_class . '">';
    }

    public function end_lvl(&$output, $depth = 0, $args = null) {
        $output .= '</ul>';
    }

    public function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
        $classes = empty($item->classes) ? array() : (array) $item->classes;
        $classes[] = 'menu-item-' . $item->ID;
        $classes[] = 'nav-item';

        if (in_array('menu-item-has-children', $classes) && $depth === 0) {
            $classes[] = 'dropdown';
        }

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

        $class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args, $depth));
        $class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';

        $output .= '<li' . $class_names . '>';

        $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 : '';

        $link_classes = array('nav-link');
        if (in_array('menu-item-has-children', $classes) && $depth === 0) {
            $link_classes[] = 'dropdown-toggle';
            $atts['data-bs-toggle'] = 'dropdown';
            $atts['aria-expanded'] = 'false';
        }

        $atts['class'] = implode(' ', $link_classes);

        $atts = apply_filters('nav_menu_link_attributes', $atts, $item, $args, $depth);

        $attributes = '';
        foreach ($atts as $attr => $value) {
            if (!empty($value)) {
                $value = ('href' === $attr) ? esc_url($value) : esc_attr($value);
                $attributes .= ' ' . $attr . '="' . $value . '"';
            }
        }

        $title = apply_filters('the_title', $item->title, $item->ID);

        $item_output = $args->before;
        $item_output .= '<a' . $attributes . '>';
        $item_output .= $args->link_before . $title . $args->link_after;
        $item_output .= '</a>';
        $item_output .= $args->after;

        $output .= apply_filters('walker_nav_menu_start_el', $item_output, $item, $depth, $args);
    }

    public function end_el(&$output, $item, $depth = 0, $args = null) {
        $output .= '</li>';
    }
}

function display_bootstrap_navbar() {
    $menu_name = 'primary';
    $locations = get_nav_menu_locations();

    if (isset($locations[$menu_name])) {
        $menu = wp_get_nav_menu_object($locations[$menu_name]);
        $menu_items = wp_get_nav_menu_items($menu->term_id);

        $output = '<nav class="navbar navbar-expand-lg navbar-light bg-light">';
        $output .= '<div class="container-fluid">';
        $output .= '<a class="navbar-brand" href="' . home_url() . '">' . get_bloginfo('name') . '</a>';
        $output .= '<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">';
        $output .= '<span class="navbar-toggler-icon"></span>';
        $output .= '</button>';
        $output .= '<div class="collapse navbar-collapse" id="navbarNav">';
        $output .= '<ul class="navbar-nav ms-auto">';

        $walker = new Bootstrap_Walker();
        $walker->walk($menu_items, 3);

        $output .= '</ul>';
        $output .= '</div>';
        $output .= '</div>';
        $output .= '</nav>';

        echo $output;
    }
}

function get_bootstrap_menu_html() {
    $menu_name = 'primary';
    $locations = get_nav_menu_locations();

    if (!isset($locations[$menu_name])) {
        return '';
    }

    $menu = wp_get_nav_menu_object($locations[$menu_name]);
    $menu_items = wp_get_nav_menu_items($menu->term_id);

    $walker = new Bootstrap_Walker();

    ob_start();
    $walker->walk($menu_items, 3);
    return ob_get_clean();
}
?>

高阶示例3:结构化数据输出与自定义HTML

结构化数据处理,支持自定义HTML输出和AJAX使用

<?php
class Structured_Data_Walker extends Walker_Nav_Menu {
    private $menu_data = array();

    public function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
        $menu_item = array(
            'id' => $item->ID,
            'title' => $item->title,
            'url' => $item->url,
            'target' => $item->target,
            'classes' => implode(' ', (array) $item->classes),
            'depth' => $depth,
            'parent' => $item->menu_item_parent,
            'children' => array()
        );

        $this->add_menu_item($menu_item, $item->menu_item_parent, $depth);
    }

    private function add_menu_item($menu_item, $parent_id = 0, $depth = 0) {
        if ($depth === 0) {
            $this->menu_data[] = $menu_item;
        } else {
            $this->add_to_parent($this->menu_data, $menu_item, $parent_id);
        }
    }

    private function add_to_parent(&$menu_items, $new_item, $parent_id) {
        foreach ($menu_items as &$item) {
            if ($item['id'] == $parent_id) {
                $item['children'][] = $new_item;
                return true;
            }
            if (!empty($item['children'])) {
                if ($this->add_to_parent($item['children'], $new_item, $parent_id)) {
                    return true;
                }
            }
        }
        return false;
    }

    public function get_menu_data() {
        return $this->menu_data;
    }
}

function get_structured_menu_data($theme_location = 'primary') {
    $locations = get_nav_menu_locations();

    if (isset($locations[$theme_location])) {
        $menu = wp_get_nav_menu_object($locations[$theme_location]);
        $menu_items = wp_get_nav_menu_items($menu->term_id);

        $walker = new Structured_Data_Walker();
        $walker->walk($menu_items, 3);

        return $walker->get_menu_data();
    }

    return array();
}

function display_custom_html_navigation() {
    $menu_data = get_structured_menu_data('primary');

    if (empty($menu_data)) {
        return;
    }

    $output = '<nav class="custom-html-nav">';
    $output .= '<div class="nav-header">';
    $output .= '<h3>网站导航</h3>';
    $output .= '</div>';
    $output .= '<div class="nav-body">';
    $output .= build_navigation_tree($menu_data);
    $output .= '</div>';
    $output .= '</nav>';

    echo $output;
}

function build_navigation_tree($menu_items, $depth = 0) {
    if (empty($menu_items)) {
        return '';
    }

    $ul_class = ($depth === 0) ? 'nav-main' : 'nav-sub nav-depth-' . $depth;

    $output = '<ul class="' . $ul_class . '">';

    foreach ($menu_items as $item) {
        $has_children = !empty($item['children']);
        $li_class = $has_children ? 'has-children' : '';
        $li_class .= in_array('current-menu-item', explode(' ', $item['classes'])) ? ' active' : '';

        $output .= '<li class="' . trim($li_class) . '">';

        $output .= '<a href="' . esc_url($item['url']) . '"';
        $output .= ' class="nav-item-link"';
        if (!empty($item['target'])) {
            $output .= ' target="' . esc_attr($item['target']) . '"';
        }
        $output .= '>';
        $output .= '<span class="nav-item-text">' . esc_html($item['title']) . '</span>';

        if ($has_children) {
            $output .= '<span class="nav-arrow">▶</span>';
        }

        $output .= '</a>';

        if ($has_children) {
            $output .= build_navigation_tree($item['children'], $depth + 1);
        }

        $output .= '</li>';
    }

    $output .= '</ul>';

    return $output;
}

function output_ajax_navigation() {
    $menu_data = get_structured_menu_data('primary');

    if (!empty($menu_data)) {
        $output = '<script>';
        $output .= 'var menuData = ' . json_encode($menu_data) . ';';
        $output .= '</script>';

        echo $output;
    }
}

class Simple_HTML_Walker extends Walker_Nav_Menu {
    public function start_lvl(&$output, $depth = 0, $args = null) {
        $output .= '<ul class="sub-menu">';
    }

    public function end_lvl(&$output, $depth = 0, $args = null) {
        $output .= '</ul>';
    }

    public function start_el(&$output, $item, $depth = 0, $args = null, $id = 0) {
        $classes = empty($item->classes) ? array() : (array) $item->classes;
        $class_names = join(' ', apply_filters('nav_menu_css_class', array_filter($classes), $item, $args, $depth));
        $class_names = $class_names ? ' class="' . esc_attr($class_names) . '"' : '';

        $output .= '<li' . $class_names . '>';
        $output .= '<a href="' . esc_url($item->url) . '"';

        if (!empty($item->target)) {
            $output .= ' target="' . esc_attr($item->target) . '"';
        }

        if (!empty($item->attr_title)) {
            $output .= ' title="' . esc_attr($item->attr_title) . '"';
        }

        $output .= '>';
        $output .= $item->title;
        $output .= '</a>';
    }

    public function end_el(&$output, $item, $depth = 0, $args = null) {
        $output .= '</li>';
    }
}

function display_simple_navigation() {
    wp_nav_menu(array(
        'theme_location' => 'primary',
        'walker' => new Simple_HTML_Walker(),
        'items_wrap' => '<ul class="simple-menu">%3$s</ul>'
    ));
}
?>

您可以根据具体需求选择合适的示例进行修改和使用。