1、获取菜单对象

static findCurrentItem(items, currentState, currentItem) {
_.forEach(items, function (item) {
if (item.state === currentState) {
currentItem.push(item);
} else if (MenuService.hasChildItems(item)) {
MenuService.findCurrentItem(item.childItems, currentState, currentItem);
}
})
} static findParentItem(items, currentItem, parentItem) {
const fatherItem = _.find(items, {id: currentItem.fatherId});
if (_.isEmpty(fatherItem)) {
_.forEach(items, function (item) {
if (MenuService.hasChildItems(item)) {
MenuService.findParentItem(item.childItems, currentItem, parentItem);
}
})
} else {
parentItem.push(fatherItem);
}
} static hasChildItems(item) {
return !!item.childItems && item.childItems.length > 0;
} getCurrentItem(menus, currentState) {
const currentItem = [];
MenuService.findCurrentItem(menus, currentState, currentItem);
return currentItem[0];
} getParentItem(menus, currentItem) {
const parentItem = [];
MenuService.findParentItem(menus, currentItem, parentItem);
return parentItem[0];
}

2、获取实际页面module

getModules(menuTree) {
const modules = [];
_.forIn(menuTree, function (value, key) {
if (!_.isEmpty(value)) {
const moduleItem = {};
const moduleItems = [];
_.set(moduleItem, 'type', key);
MenuService.findModuleItem(moduleItems, value);
_.set(moduleItem, 'state', moduleItems[0]);
modules.push(moduleItem);
}
});
return modules;
} static findModuleItem(moduleItems, menuTreeValue) {
_.forEach(menuTreeValue, function (item) {
if (item.state.indexOf('.') !== -1) {
moduleItems.push(_.get(item, 'state'));
} else if (MenuService.hasChildItems(item)) {
MenuService.findModuleItem(moduleItems, item.childItems);
}
})
}

3、获取默认路由

getDefaultState(menuTree) {
const modules = this.getModules(menuTree);
if (!_.isEmpty(modules)) {
return _.get(modules[0], 'state');
}
}

4、获取menus

getMenu() {
return new Promise((resolve, reject) => {
axiosService.request({
url: '/api/menus',
method: 'GET'
}).then(res => {
const menuTree = {};
const navigators = {};
_.forEach(res.data, function (item) {
_.set(menuTree, item.state, item.childItems);
_.set(navigators, item.state, item.name);
});
const menu = {
menuTree,
navigators,
defaultState: this.getDefaultState(menuTree),
modules: this.getModules(menuTree)
};
typeof resolve === 'function' && resolve(menu);
}).catch(error => {
typeof reject === 'function' && reject(error);
})
})
} getSidebarMenu(menuTree, nav) {
return _.result(menuTree, nav);
}

menuTree: 集合,里面包含一个nav,一个对应该nav的菜单item

[{"nav01": [nav01.menus01]},{"nav02": [nav01.menus02]}];

navigators: 一个nav,一个对应nav的名字

[{"nav01": "nav01.name"},{"nav02": "nav01.name"}];

modules: 一个nav,一个对应nav的第一个路由

[{"nav01": "nav01.defaultState01"},{"nav02": "nav01.defaultState02"}];

redux menu data:

import React from "react";
import {connect} from "react-redux";
import {withRouter} from "react-router-dom";
import {Icon} from "antd";
import _ from "lodash";
import "./index.scss" const mapStateToProps = state => {
return {
menuData: state.MenuReducer.data
}
}; class Sidebar extends React.Component { constructor(props) {
super(props);
this.currentState = props.location.pathname;
this.menus = _.result(props.menuData.menuTree, props.nav);
} componentDidMount() {
const defaultNavItem = this.getDefaultNavItem();
if (defaultNavItem === undefined) {
this.props.history.replace('/forbidden');
return;
}
this.setActiveNavItem(defaultNavItem);
this.openNavItem(defaultNavItem);
if (this.hasChildItems(defaultNavItem)) {
this.setActiveChildNavItem(defaultNavItem.childItems);
}
} getDefaultNavItem() {
const currentState = this.currentState;
return _.find(this.menus, function (navItem) {
if (navItem.state === currentState || _.some(navItem.childItems, {state: currentState})) {
return navItem;
}
})
} setActiveNavItem(navItem) {
if (this.hasChildItems(navItem)) {
this.clearParentActiveStatus();
} else {
this.clearActiveStatusWithChildItems();
navItem.isActive = true;
if (!!navItem.state) {
this.props.history.replace(navItem.state);
}
}
} setActiveChildNavItem(childNavItems) {
const currentState = this.currentState;
this.clearActiveStatusWithChildItems();
if (_.isArray(childNavItems)) {
childNavItems.forEach(function (navItem) {
navItem.isActive = navItem.state === currentState;
});
} else {
childNavItems.isActive = true;
}
} openNavItem(navItem) {
navItem.isOpen = this.hasChildItems(navItem);
this.forceUpdate();
} onOpenNavItem(navItem) {
if (this.hasChildItems(navItem)) {
navItem.isOpen = !navItem.isOpen;
} else {
navItem.isOpen = false;
}
this.forceUpdate();
} clearParentActiveStatus() {
this.menus.forEach(function (navItem) {
navItem.isActive = false;
})
} clearActiveStatusWithChildItems() {
this.menus.forEach(function (navItem) {
navItem.isActive = false;
navItem.childItems.forEach(function (childItem) {
childItem.isActive = false;
})
})
} hasChildItems(navItem) {
return !!navItem.childItems && navItem.childItems.length > 0;
} menuIcon(navItem) {
return <Icon type={navItem.isOpen ? 'caret-down' : 'caret-right'}/>
} openOrActiveClass(navItem) {
const basic = "nav-item";
const openClass = navItem.isOpen ? "is-open" : "";
const activeClass = navItem.isActive ? "active" : "";
return basic + " " + openClass + " " + activeClass;
} activeClass(navItem) {
const basic = "child-nav-item";
const activeClass = navItem.isActive ? "active" : "";
return basic + " " + activeClass;
} render() {
return (
<aside className="app-sidebar">
<ul className="list-unstyled menu">
{
this.menus && this.menus.map((navItem, index) => {
return (
<li key={'li_' + index} className={this.openOrActiveClass(navItem)}>
<span key={'span_' + index}
className="item-name nav-item-content"
onClick={() => {
this.setActiveNavItem(navItem);
this.onOpenNavItem(navItem)
}}>
{this.hasChildItems(navItem) ? this.menuIcon(navItem) : null}
{navItem.name}
</span>
{
navItem.isOpen ?
<ul key={'subMenu_ul'} className="list-unstyled sub-menus">
{
navItem.childItems.map((childItem, itemIndex) => {
return (
<li key={'submenu_li_' + itemIndex}
className={this.activeClass(childItem)}
onClick={() => {
this.setActiveChildNavItem(childItem);
this.setActiveNavItem(childItem)
}}>
<a className="item-name">{childItem.name}</a>
</li>
)
})
}
</ul> : null
}
</li>
)
})
}
</ul>
</aside>
)
}
} export default withRouter(connect(mapStateToProps)(Sidebar));

scss:

@import "../../styles/varibles";

.app-sidebar {
overflow: hidden;
width: 180px; > ul > li {
position: relative;
font-size: $font-lg;
border-bottom: $border;
border-right: $border;
border-left: $border; &:first-child {
border-top: $border;
border-top-right-radius: $border-radius;
border-top-left-radius: $border-radius;
} &:last-child {
border-bottom-right-radius: $border-radius;
border-bottom-left-radius: $border-radius;
}
} .active {
color: $primary-color;
font-weight: bold;
border-left: 3px solid $primary-color;
background-color: $item-active-bg-color;
a {
font-weight: bold;
color: $primary-color;
}
} .nav-item {
.item-name {
margin-left: 30px;
height: 50px;
line-height: 50px;
}
.anticon {
position: absolute;
height: 50px;
line-height: 50px;
left: 7px;
font-size: $font-sm;
color: $title-color;
} &.is-open {
.anticon {
color: $primary-color;
}
.nav-item-content {
color: $title-color;
font-weight: bold;
}
}
&:hover {
.anticon,
.nav-item-content {
color: $primary-color;
}
}
&:active {
.nav-item-content {
color: $primary-color;
font-weight: bold;
}
}
.sub-menu {
border-top: none;
font-size: $font-sm; .item-name {
height: 40px;
line-height: 40px;
} .child-nav-item.active {
.item-name {
color: $primary-color;
font-weight: bold;
}
}
}
}
}

react: menuService的更多相关文章

  1. react: navigator

    1.page js import React from "react"; import {Link} from "react-router-dom"; impo ...

  2. react组件的生命周期

    写在前面: 阅读了多遍文章之后,自己总结了一个.一遍加强记忆,和日后回顾. 一.实例化(初始化) var Button = React.createClass({ getInitialState: f ...

  3. 十分钟介绍mobx与react

    原文地址:https://mobxjs.github.io/mobx/getting-started.html 写在前面:本人英语水平有限,主要是写给自己看的,若有哪位同学看到了有问题的地方,请为我指 ...

  4. RxJS + Redux + React = Amazing!(译一)

    今天,我将Youtube上的<RxJS + Redux + React = Amazing!>翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: https:/ ...

  5. React 入门教程

    React 起源于Facebook内部项目,是一个用来构建用户界面的 javascript 库,相当于MVC架构中的V层框架,与市面上其他框架不同的是,React 把每一个组件当成了一个状态机,组件内 ...

  6. 通往全栈工程师的捷径 —— react

    腾讯Bugly特约作者: 左明 首先,我们来看看 React 在世界范围的热度趋势,下图是关键词“房价”和 “React” 在 Google Trends 上的搜索量对比,蓝色的是 React,红色的 ...

  7. 2017-1-5 天气雨 React 学习笔记

    官方example 中basic-click-counter <script type="text/babel"> var Counter = React.create ...

  8. RxJS + Redux + React = Amazing!(译二)

    今天,我将Youtube上的<RxJS + Redux + React = Amazing!>的后半部分翻译(+机译)了下来,以供国内的同学学习,英文听力好的同学可以直接看原版视频: ht ...

  9. React在开发中的常用结构以及功能详解

    一.React什么算法,什么虚拟DOM,什么核心内容网上一大堆,请自行google. 但是能把算法说清楚,虚拟DOM说清楚的聊聊无几.对开发又没卵用,还不如来点干货看看咋用. 二.结构如下: impo ...

随机推荐

  1. springmvc 资源国际化

    <!-- 关于国际化: 1. 在页面上能够根据浏览器语言设置的情况对文本(不是内容), 时间, 数值进行本地化处理 2. 可以在 bean 中获取国际化资源文件 Locale 对应的消息 3. ...

  2. slf4j-api、slf4j-log4j12以及log4j之间什么关系?

    几乎在每个jar包里都可以看到log4j的身影,在多个子工程构成项目中,slf4j相关的冲突时不时就跳出来让你不爽,那么slf4j-api.slf4j-log4j12还有log4j他们是什么关系?我把 ...

  3. POJ 2516 Minimum Cost (KM最优匹配)

    题意:有N家家店,每家店都对K种货物有需求:同时有M家仓库,对K钟货物有供应.对于每种货物,每个仓库送至每家店都有自己的单位费用.求满足所有店所有货物的最小费用 分析:对于每一种货物,如果总需求大于总 ...

  4. js实现删除弹框确认

    JSP页面代码如下: <%@ page language="java" contentType="text/html; charset=UTF-8"%&g ...

  5. 使用Socket&反射&Java流操作进行方法的远程调用(模拟RPC远程调用)

    写在前面 阅读本文首先得具备基本的Socket.反射.Java流操作的基本API使用知识:否则本文你可能看不懂... 服务端的端口监听 进行远程调用,那就必须得有客户端和服务端.服务端负责提供服务,客 ...

  6. 【c++习题】【17/4/16】动态分配内存

    #include<iostream> #include<cstring> #define N 100 using namespace std; class String{ pu ...

  7. ubuntu 致命错误: zlib.h:没有那个文件或目录【转】

    本文转载自:https://blog.csdn.net/u013359794/article/details/44922685?locationnum=15&fps=1 编译时,出现错误,提示 ...

  8. 用adb 启动camera

    adb shell am start -a android.media.action.STILL_IMAGE_CAMERA  启动camera adb shell input keyevent 27 ...

  9. Spring AOP 前奏--动态代理

  10. [ SSH 两种验证方式原理 ]

    SSH登录方式主要分为两种: 1. 用户名密码验证方式 说明: (1) 当客户端发起ssh请求,服务器会把自己的公钥发送给用户: (2) 用户会根据服务器发来的公钥对密码进行加密: (3) 加密后的信 ...