如何为每个子菜单添加ID属性?

时间:2021-05-17 作者:nsog8sm43x

我想添加一个ID attribute 到每个列表<ul> submenu. 我正在使用Walker class 扩大我已经设法修改了一些元素,但我只能解决这个问题。我需要ID属性来展开移动版本中的菜单。不幸的是,我不知道该怎么做。菜单的工作方式是button 在每个子菜单前面data-target attribute 目标位于该子菜单的ID中。

这是我的functions.php 文件看起来像Walker class extension

class Walker_N_Menu extends Walker_Nav_Menu {

    function start_lvl( &$output, $depth = 0, $args = array() ) {
        // Depth-dependent classes.
        $indent = ( $depth > 0  ? str_repeat( "\\t", $depth ) : \'\' ); // code indent
        $display_depth = ( $depth + 1); // because it counts the first submenu as 0
        $classes = array(
            \'sub-menu\',
            \'collapse\',
            \'menu-depth-\' . $display_depth
        );
        $button = ( $depth > 0 ) ? \'<button class="btn-submenu" data-target="#submenu1"><ion-icon name="chevron-forward-outline" role="img" class="md hydrated" aria-label="chevron forward outline"></ion-icon></button>\' : \'<button class="btn-submenu" data-target="#submenu1"><ion-icon name="chevron-down-outline" role="img" class="md hydrated" aria-label="chevron down outline"></ion-icon></button>\';
        $class_names = implode( \' \', $classes );

        // Build HTML for output.
        $output .= "\\n" . $indent . $button . "\\n" . $indent . \'<ul id="submenu1" class="\' . $class_names . \'">\' . "\\n";
    }

    function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
        global $wp_query;
        $indent = ( $depth > 0 ? str_repeat( "\\t", $depth ) : \'\' ); // code indent

        // Depth-dependent classes.
        $depth_classes = array(
            ( $depth == 0 ? \'nav-item\' : \'submenu-item\' ),
            \'menu-item-depth-\' . $depth
        );
        $depth_class_names = esc_attr( implode( \' \', $depth_classes ) );

        // Passed classes.
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $class_names = esc_attr( implode( \' \', apply_filters( \'nav_menu_css_class\', array_filter( $classes ), $item ) ) );

        // Build HTML.
        $output .= $indent . \'<li id="nav-menu-item-\'. $item->ID . \'" class="\' . $depth_class_names . \' \' . $class_names . \'">\';

        // Link 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        ) .\'"\' : \'\';
        $attributes .= \' class="\' . ( $depth == 0 ? \'nav-link\' : \'\' ) . \'"\';

        // Build HTML output and pass through the proper filter.
        $item_output = sprintf( \'%1$s<a%2$s>%3$s%4$s%5$s</a>%6$s\',
            $args->before,
            $attributes,
            $args->link_before,
            apply_filters( \'the_title\', $item->title, $item->ID ),
            $args->link_after,
            $args->after
        );
        $output .= apply_filters( \'walker_nav_menu_start_el\', $item_output, $item, $depth, $args );
    }
}
由于我不知道如何正确执行此操作,因此代码此时会为每个子菜单生成相同的ID。最后,我希望每个按钮都有一个不同的数据目标属性,该属性将与它所覆盖的每个子菜单ID相匹配。

除了在论坛中搜索类似主题外,我还尝试使用preg_replace 函数,将该函数添加到functions.php 文件:

function change_submenu_id( $menu ) {
    for ($i = 0; $i < 10; $i++) {
        $menu = preg_replace( \'/<ul id="" class="sub-menu/\' , \'<ul id="\'. $i .\'" class="sub-menu\' ,$menu);
    }
}
add_filter( \'wp_nav_menu\', \'change_submenu_id\' );
不幸的是,我做错了什么,这个函数为每个ID生成数字0。。。。

我将非常感谢您的帮助。

1 个回复
SO网友:Pat J

在您的Walker_N_Menu 类别的start_lvl() 方法,您正在设置<ul>\'sidsubmenu1. 您可以对此进行更改(在本例中,使用$depth 参数传递给start_lvl()) 要保持唯一性:

function start_lvl( &$output, $depth = 0, $args = array() ) {
    // Depth-dependent classes.
    $indent = ( $depth > 0  ? str_repeat( "\\t", $depth ) : \'\' ); // code indent
    $display_depth = ( $depth + 1); // because it counts the first submenu as 0
    $classes = array(
        \'sub-menu\',
        \'collapse\',
        \'menu-depth-\' . $display_depth
    );
    $button = ( $depth > 0 ) ? \'<button class="btn-submenu" data-target="#submenu1-\' . $depth . \'"><ion-icon name="chevron-forward-outline" role="img" class="md hydrated" aria-label="chevron forward outline"></ion-icon></button>\' : \'<button class="btn-submenu" data-target="#submenu1-\' . $depth . \'"><ion-icon name="chevron-down-outline" role="img" class="md hydrated" aria-label="chevron down outline"></ion-icon></button>\';
    $class_names = implode( \' \', $classes );

    // Build HTML for output.
    $output .= "\\n" . $indent . $button . "\\n" . $indent . \'<ul id="submenu1-\' . $depth . \'" class="\' . $class_names . \'">\' . "\\n";
}
如果一个页面中有多个菜单需要此选项,则应能够在$args 阵列到start_lvl() 方法

至于为什么add_filter() 代码似乎工作不正常:连接到过滤器的函数需要return 一般来说,这是一个值,函数不会返回任何内容。此外,运行for() 循环使用这些值不会达到预期效果;我建议,如果您返回一个值(即,return $menu; 在函数末尾),您会发现所有值都是9.