修改Walker_Nav_Menu时,将‘Has_Child’类添加到父项li

时间:2011-05-10 作者:patnz

我正在为wp\\U nav\\U菜单编写一个定制的walker类,并希望能够指定li是否包含子菜单。因此,我希望我的标记是:

<li class="has_children [other-wordpress-classes]">
    <a class="parent-link">Some item</a>
    <ul class="sub-menu">
我知道如何添加和删除类很好,我只是找不到任何东西来告诉我当前项目是否有子项目。

有什么想法吗?

提前谢谢。

5 个回复
最合适的回答,由SO网友:Jan Fabry 整理而成

start_el() 应在其$args 参数,但它显示WordPress only fills this in if $args is an array, 而对于自定义导航菜单,它是一个对象。这在中报告a Trac ticket. 但没问题,如果您还重写display_element() 方法(因为这是访问子元素数组最容易的地方):

class WPSE16818_Walker extends Walker_Nav_Menu
{
    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output )
    {
        $id_field = $this->db_fields[\'id\'];
        if ( is_object( $args[0] ) ) {
            $args[0]->has_children = ! empty( $children_elements[$element->$id_field] );
        }
        return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }

    function start_el( &$output, $item, $depth, $args ) {
        if ( $args->has_children ) {
            // ...
        }
    }

SO网友:rjb

Update: 截至年月日WordPress 3.7 (2013年10月),添加了CSS类以指示主题菜单中的子菜单项和页面-无需使用自定义walker,因为它在WordPress core中得到了处理。

CSS类被命名为menu-item-has-childrenpage_item_has_children.


要想为匆忙中的任何人提供完整的解决方案(归功于Jan Fabry之前的回答),请参阅下面的完整实现。

在主题模板中输出导航:

wp_nav_menu( array(
    \'theme_location\' => \'navigation-primary\',
    \'container\' => false,
    \'container_class\' => \'\',
    \'container_id\' => \'\',
    \'menu_class\' => \'\',
    \'menu_id\' => \'\',
    \'walker\' => new Selective_Walker(),
    \'depth\' => 2
    )
);
然后,在主题中包括以下内容functions.php:

class Selective_Walker extends Walker_Nav_Menu {
    function display_element( $element, &$children_elements, $max_depth, $depth=0, $args, &$output ) {
        $id_field = $this->db_fields[\'id\'];

        if ( is_object( $args[0] ) ) {
            $args[0]->has_children = !empty( $children_elements[$element->$id_field] );
        }

        return parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
    }

    function start_el( &$output, $item, $depth, $args ) {
        if ( $args->has_children ) {
            $item->classes[] = \'has_children\';
        }

        parent::start_el(&$output, $item, $depth, $args);
    }
}
生成的HTML输出类似于以下内容:

<ul>
    <li><a href="#">Home</a></li>
    <li class="has_children"><a href="#">About</a>
        <ul class="sub-menu">
            <li><a href="#">Our Mission</a></li>
        </ul>
    </li>
    <li><a href="#">Services</a></li>
    <li class="has_children"><a href="#">Products</a>
        <ul class="sub-menu">
            <li><a href="#">Lorem Ipsum</a></li>
            <li><a href="#">Lorem Ipsum</a></li>                
        </ul>
    </li>
    <li><a href="#">Contact Us</a></li>
</ul>
有关使用WordPress的walker类的更多信息,请参阅Understanding the Walker Class.

享受

SO网友:kaiser

这个函数正是您想要的。它还向您展示了一种修改导航菜单项的非常有效的方法。此外,您还可以通过项目过滤器打开它以获得更高级(如子主题)的功能:

/**
 * Classes for a navigation named "Topnav" in the nav location "top".
 * Shows examples on how to modify the current nav menu item
 * 
 * @param (object) $items
 * @param (object) $menu
 * @param (object) $args
 */
function wpse16818_nav_menu_items( $items, $menu, $args )
{
    # >>>> start editing

    // examples for possible targets
    $target[\'name\'] = \'Topnav\';
    // The targeted menu item/s
    $target[\'items\'] = array( (int) 6 );

    # <<<< stop editing

    // filter for child themes: "config_nav_menu_topnav"
    $target = apply_filters( \'config_nav_menu_\'.strtolower( $target[\'name\'] ), $target );

    // Abort if we\'re not with the named menu
    if ( $menu->name !== $target[\'name\'] ) 
        return;

    foreach ( $items as $item )
    {
        // Check what $item contains
        echo \'<pre>\'; print_r($item); echo \'</pre>\';

        // First real world example:
        $item->classes = \'span-4\';

        // Second real world example:
        // Append this class if we are in one of the targeted items
        if ( in_array( (int) $item->menu_order, $target[\'items\'] ) )
            $item->classes .= \' last\';
    }

    return $items;
}
add_filter( \'wp_get_nav_menu_items\', \'wpse16818_nav_menu_items\', 10, 3 );
是的,几乎在所有情况下,都不需要定制助行器

SO网友:alexndm

如果你想做下拉列表,你可以只使用css。在WP中自定义导航,WordPress会自动分配类。子菜单至子菜单ul。尝试此CSS

    nav li {position:relative;}
   .sub-menu {display:none; position:absolute; width:300px;}
    nav ul li:hover ul {display:block;}
您可能想添加一些jQuery来增加一些趣味,但这应该会为您提供一个可用的下拉菜单。

SO网友:yaroslav
if ( $this->has_children ) {
    $item_output .= \'has_children\';
}
结束

相关推荐

Menu API not switching menus?

我正在使用菜单API,我想切换到其他菜单,但出于某种原因,它保留了第一个菜单这是我的密码在函数中。php add_action( \'init\', \'register_my_menus\',10 ); function register_my_menus() { register_nav_menu(\'main-navigation\', \'Main Navigation\'); } 下面是我的主题文件(header.ph