WordPress菜单自定义Walker类

时间:2012-05-16 作者:abrudtkuhl

我们使用jQuery UI accordian在侧栏中呈现菜单。我们已经编写了标记和javascript,我只是想让wp\\u nav\\u菜单输出我们已经编写的相同标记。我正在创建一个自定义Walker类,扩展Walker\\u Nav\\u菜单。

这是我们想要的加价

<h2><a href="#">Parent Item</a></h2>
<div>
    <ul>
    <li><a href="">Child Item 1</a></li>
    <li><a href="">Child Item 2</a></li>
    <li><a href="">Child Item 3</a></li>
    <li><a href="">Child Item 4</a></li>
    <li><a href="">Child Item 5</a></li>
    </ul>
</div>
<h2><a href="#">Parent Item 2</a></h2>
<div>
    <ul>
    <li><a href="">Child Item 1</a></li>
    <li><a href="">Child Item 2</a></li>
    <li><a href="">Child Item 3</a></li>
    <li><a href="">Child Item 4</a></li>
    <li><a href="">Child Item 5</a></li>
    </ul>
</div>
不幸的是,我无法让自定义Walker类按照我的意愿输出标记。任何关于Walker课程的示例或教程都会很好。仍然没有在SE或Google上找到我想要的东西。

谢谢

2 个回复
最合适的回答,由SO网友:Stephen Harris 整理而成

最简单的方法是扩展Walker_Nav_Menu 类而不是Walker_Class, (由于父/ID字段已设置,并且通常需要维护一些标记等)。

主要方法有:

  • start_el / end_el - 负责在列表中显示元素start_lvl / end_lvl - 负责显示子菜单walkdisplay_element 这在很大程度上只是控制了课堂的机制。在大多数情况下,上述四个函数是需要在扩展类中修改的函数。

    这就是说,您所追求的结构并不是真正的嵌套结构,因此您在这里并没有完全使用Walker类。然而,这门定制步行课程将为您提供最便捷的方式:

    class SH_Accordian_Walker extends Walker_Nav_Menu {  
    
        //Start \'sub menu\'
        function start_lvl(&$output, $depth=0, $args=array()) {  
    
            if($depth > 0)
               return parent::end_lvl(&$output, $depth);
    
            $output .= \'<div><ul>\';
        }  
    
        //End \'sub menu\'
        function end_lvl(&$output, $depth=0, $args=array()) {  
            if($depth > 0)
               return parent::end_lvl(&$output, $depth);
    
            $output .= \'</ul></div>\';
        }  
    
        // Start element
        function start_el(&$output, $item, $depth=0, $args=array()) {  
            if( 0 == $depth ){
                 $output.= \'<h2><a href="\'.esc_attr($item->url).\'">\'.apply_filters( \'the_title\', $item->title, $item->ID ).\'</a></h2>\';
                 return; 
            }
    
            // level 2+
            parent::start_el(&$output, $item, $depth, $args);  
        }  
    
        // Don\'t need to add any output - sub menus aren\'t nested
        function end_el(&$output, $item, $depth=0, $args=array()) {
           if($depth > 0)
             parent::end_el(&$output, $item, $depth);
        }  
    
    } 
    
    这只是一个非常简单的类来演示您需要做什么。由于你的结构不是嵌套的,如果我们再往下走超过两层(即孙子女),这看起来可能不太正确。

    用法:

    wp_nav_menu( array( 
           \'theme_location\' => \'primary\',
           \'walker\'=> new SH_Accordian_Walker, 
           \'depth\'=>2,
           \'items_wrap\'=> \'%3$s\'
         ) );
    
    (我最近写了一篇关于Walker课程的教程:http://wp.tutsplus.com/tutorials/creative-coding/understanding-the-walker-class/ 您可能会觉得有用)

SO网友:abrudtkuhl

但愿我在下兔子洞之前看到你的答案。然而,我已经能够使用Walker类的扩展复制我们的设计器提供的标记,并且它与jQuery UI Accordion配合得很好。

    class sidebar_nav_walker extends Walker_Nav_Menu {
    function start_el(&$output, $item, $depth, $args) {
      global $wp_query;
      if (0 == $depth) {
        // parent item
        $output .= \'<h2>\';

        $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        ) .\'"\' : \'\';

        $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 );
        $output .= \'</h2>\';

      } else {
        // child items
        $class_names = $value = \'\';
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
        $classes[] = \'menu-item-\' . $item->ID;

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

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

        $output .= $indent . \'<li\' . $id . $value . $class_names .\'>\';

        $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        ) .\'"\' : \'\';

        $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 start_lvl(&$output, $depth, $args=array()) {  
      $output .= "\\n<div><ul>\\n";  
  }

  // Displays end of a level. E.g \'</ul>\'  
  // @see Walker::end_lvl()  
  function end_lvl(&$output, $depth, $args=array()) { 
      $output .= "</ul></div>\\n";  
  }

    /**
     * @see Walker::end_el()
     * @since 3.0.0
     *
     * @param string $output Passed by reference. Used to append additional content.
     * @param object $item Page data object. Not used.
     * @param int $depth Depth of page. Not Used.
     */
    function end_el(&$output, $item, $depth) {

  }
}
这让我走得很远。但我仍然对wp\\U nav\\U菜单在UL中包装整个内容存在问题。这打破了jQuery手风琴脚本。所以我需要删除它,在实验结束后,用自定义Walker呈现菜单,如下所示。。。

  <nav id="nav">
    <?php
      $menu = wp_nav_menu(
        array(
          \'container\' =>  false,
          \'echo\'  =>  false,
          \'before\'  =>  \'\',
          \'after\' =>  \'\',
          \'link_before\' =>  \'\',
          \'link_after\'  =>  \'\',
          \'walker\'  =>  new sidebar_nav_walker()
        )
      );
      echo preg_replace( array( \'#^<ul[^>]*>#\', \'#</ul>$#\' ), \'\', $menu );
    ?>
  </nav>
注意:我告诉菜单不要在参数中重复自己。相反,我在其上运行正则表达式来删除父级UL。

同样值得注意的是。。如果你不告诉jQuery手风琴不要自动高度,这看起来就像垃圾。

$(function() {
    $("#nav").accordion({
            collapsible: true,
            autoHeight: false
    });
});
除了WP添加的类之外,结果与我的设计器中的原始标记有些接近。

结束