Monthly Archives: July 2018

Mega Menu设计实现小结

Mega Menu作为一种导航UI元素,在越来越多的大型应用中得到使用,尤其是当功能模块页面很多,Mega Menu提供给用户更丰富的上下文信息,友好一致的导航体验。
它一般长这样子,

这样子,

这次的设计跟传统Mega Menu不太一样,它不是为一个单体应用设计Mega Menu,而是为了适应很多个原来独立的产品以suite的形式提供给客户的产品策略。当前实际的状态是提供单独的landing page,每个应用对应着一个链接,每个单独的产品都保持自己的导航菜单,同时添加返回landing page的菜单,造成了在应用之间切换的体验对客户很不友好。现在要求在suite层面上提供一个Mega Menu的实现,提供统一功能的UI界面,比如用户信息,搜索,登录,通知,同时允许各个应用可以一定程度上可以定制扩展Mega Menu的UI和功能,比如应用可以在指定区域,左,中,右去添加菜单项并设定相应的功能;可以提供自己的dropdown区域的UI实现;原来各个应用的菜单行为要保留,比如搜索,通知,在不同的应用上下文显示正确的搜索结果;最后,要求对各个应用的代码尽可能少的侵入,各个应用可以用最少的开发周期去完成集成。

1. 基于React开发

<MegaMenu>
    <MegaMenu.Item ... /> 
    <MegaMenu.Item ... />
</MegaMenu>

2. 通过设定webpack配置output.library = “MegaMenu” 打包暴露给老代码的api尽可能简单

<script type="text/javascript" src="MegaMenu.js"></script>
<script type="text/javascript">
  var megaMenu = new MegaMenu(items);
  megaMenu.render(domElement);
</script>

3. items的数据结构

var items = [
  { icon: 'fa fa-bars', id: 'Products', type:'pusher',items:[
      { text: 'ProductA', id: 'ProductAId' },
      { text: 'ProductB', id: 'ProductBId' }
  ] },
  { text: 'item1', id: '1' },
  { text: 'item2', id: '2' },
  { text: 'item3', id: '3' },
  {
    text: 'item4', id: '4', type: 'dropdown', items: [
      { text: 'item4-1', id: '4-1' },
      { text: 'item4-2', id: '4-2' },
      { text: 'item4-3', id: '4-3' },
      { text: 'item4-4', id: '4-4' },
      { text: 'item4-5', id: '4-5' }
    ]
  },
  { text: 'item5', id: '5' },
  { text: 'item6', id: 'customizeddropdown', type:'dropdown' },

  {
    text: 'User', type: 'dropdown', id:'user', items: [
      { text: 'Logout', id: 'logout' }
    ],
    location: 'right'
  },
  {
    text: 'Settings',
    id: 'settings',
    icon: 'fa fa-cogs',
    location: 'right'
  }
];

4. 通过事件来实现UI外观和行为的扩展定制化,event bus的实现可以直接用nodejs的events.EventEmitter

megaMenu.addListener(MegaMenu.Events.ITEM_RENDERING_EVENT, function(id,itemContainer){
  console.log('item id=' + id + ' is rendering in ' + itemContainer);
}); 

megaMenu.addListener(MegaMenu.Events.DROPDOW_EXPANDING_EVENT, function(id, dropDownContainer) {
  console.log('item id=' + id + ' is expanding in ' + dropDownContainer);
});

megaMenu.addListener(MegaMenu.Events.PUSHER_PUSHING_EVENT, function(id, pusherContainer) {
  console.log('item id=' + id + ' is pushing in ' + pusherContainer);
});

megaMenu.addListener(MegaMenu.Events.ITEM_CLICKED_EVENT, function(id) {
  console.log('item id=' + id + ' is clicked');
});

最后,因为我的日常工作是一个后端Java程序员,如果你是个前端架构师,希望能和你探讨更好的方案。