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. macos没有任何来源怎么解决?

    打开终端,输入如下命令即可: sudo spctl --master-disable

  2. numpy.linspace介绍

    numpy.linspace:在指定范围内返回均匀间隔的数组 In [12]: import numpy as np In [13]: result = np.linspace(1,10) #默认生成 ...

  3. mysql的-F与master-data理解(一个小型的big-log恢复)

    例子: 使用mysqlbin-log恢复,有两种情况,一个是停数据库,一个是不停 在不停数据库的情况下,为了防止新的写入,需要将bin-log切割,然后新的数据会保存在新的bin-log里面 在此之前 ...

  4. Python(面向对象编程—1)

    class tst: l=[] x=1 a=tst() b=tst() a.l.append('a') b.l.append('b') a.x='a' b.x='b' print(a.l,a.x) # ...

  5. 本地连不上远程mysql数据库(2)

    Host is not allowed to connect to this MySQL server解决方法 今天在ubuntu上面装完MySQL,却发现在本地登录可以,但是远程登录却报错Host ...

  6. 微服务与SOA

    微服务跟SOA有什么区别呢,可以把微服务当做去除了ESB的SOA.ESB是SOA架构中的中心总线,拓扑结构应该是星形的,而微服务是去中心化的分布式软件架构. 一.巨石(monolith) web应用程 ...

  7. C++类中成员变量的初始化总结

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  8. Linux下解压分包文件zip(zip/z01/z02)【转】

    本文转载自:https://www.cnblogs.com/EasonJim/p/7227109.html?utm_source=itdadao&utm_medium=referral Lin ...

  9. LAMP服务器的搭建

    LAMP是一组构建Web应用平台的开源软件解决方案,它是一个开源套件组合.其中L:linux,A :Apache HTTP服务器,M : MySQL或MariaDB,P : perl或Python.这 ...

  10. Spring Cloud2.0之Oauth2环境搭建(授权码模式和密码授权模式)

    oauth2 server 微服务授权中心,    github源码  https://github.com/spring-cloud/spring-cloud-security 对微服务接口做一些权 ...