react style: 二级菜单
1、样式
@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 {
border-left: 3px solid $primary-color;
background-color: $item-active-bg-color;
a {
font-weight: bold;
}
}
.nav-item {
.item-name {
margin-right: 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;
}
}
}
}
2、js文件
import React from "react";
import {withRouter} from "react-router-dom";
import {Icon} from "antd";
import _ from "lodash";
const menus = [];
const currentState = ''; class Sidebar extends React.Component { 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 = currentState;
return _.find(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 = 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() {
menus.forEach(function (navItem) {
navItem.isActive = false;
})
} clearActiveStatusWithChildItems() {
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">
{
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(Sidebar);
3、数据
[
{
"description": "userCanGetMenus",
"request": {
"method": "GET",
"uri": "/api/menus"
},
"response": {
"status": 200,
"json": {
"id": "DEMO0000",
"fatherId": "00000000",
"state": "process",
"name": "运营流程",
"childItems": [
{
"id": "DEMO1000",
"fatherId": "DEMO0000",
"state": "/process.personal-task-pool",
"name": "个人任务池",
"childItems": []
},
{
"id": "DEMO2000",
"fatherId": "DEMO0000",
"state": "/process.common-task-pool",
"name": "公共任务池",
"childItems": []
},
{
"id": "DEMO1000",
"fatherId": "DEMO0000",
"state": "/process.launch",
"name": "流程发起",
"childItems": []
},
{
"id": "DEMO1000",
"fatherId": "DEMO0000",
"state": "/process.search",
"name": "流程查询",
"childItems": []
}
]
}
}
}
]
react style: 二级菜单的更多相关文章
- react 侧栏二级菜单组件
侧边栏菜单组件 component 下新建menu文件,menu下建index.jsx和subitem.jsx index.jsx import React, { Component } from ' ...
- Jquery垂直下拉二级菜单
自己做了一个基于Jquery 的垂直下拉二级菜单功能,直接看图: Html的代码如下: <!DOCTYPE html> <html> <head> <meta ...
- JS实现的简单横向伸展二级菜单
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- JS-鼠标经过显示二级菜单
在css处添加了border样式为了看得更清楚——源代码有一个程序漏洞,存在一个很烦人的大bug. <ul class="nav"> <li class=&quo ...
- 转:jQuery弹出二级菜单
<html> <head> <meta http-equiv="content-type" content="text/html; char ...
- html+css二级菜单制作!
二级菜单!!<!DOCTYPE html<html lang="e<head> <meta charset="UTF-8"> < ...
- js运动:多div变宽、二级菜单
定时器及运动函数. 多div变宽: <!-- Author: XiaoWen Create a file: 2016-12-13 09:36:30 Last modified: 2016-12- ...
- javascript 特效实现(3)—— 鼠标滑过显示二级菜单效果
1. 关键代码:使用 switch 或 if 判断语句,改变对应的二级菜单显示方式为 block 或 none function selectTabMenu(i){ switch(i){ case 7 ...
- jquery垂直展开折叠手风琴二级菜单
摘要:jquery实现垂直展开二级菜单 最近新开发一个简单项目,用到左侧两级的菜单.找找了手头的文件,竟然没有现成的代码,算了,去网上找找整理下吧. 注:jquery-1.8.3.min.js需要下载 ...
随机推荐
- Flume日志收集 总结
Flume是一个分布式.可靠.和高可用的海量日志聚合的系统,支持在系统中定制各类数据发送方,用于收集数据: 同时,Flume提供对数据进行简单处理,并写到各种数据接受方(可定制)的能力. (1) 可靠 ...
- knockout 学习使用笔记-----event绑定传参ko属性
在绑定event的时候,需要传入ViewModal 本身的属性值(其实没必要,js直接能获取到,此处为测试相关参数的传递),如果不加(),会将绑定的function传进event(至于为嘛传了个fun ...
- asp.net MVC 强类型视图表单Ajax提交的注意事项
xmfdsh这几天遇到这么一个问题,在MVC中通过model模型生成的强类型视图的表单,在提交后的回调函数并没有发挥作用.如下图: 如上图,无论是通过Ajax.BeginForm或者Html.Begi ...
- Go语言学习之运算符(The way to go)
生命不止,继续go go go 今天介绍go中的运算符. 运算符大概分为: Arithmetic Operators Relational Operators Logical Operators Bi ...
- 安装专业版的linux的方法 图解安装专业版的linux
按装一个linux系统其实很简单,不再像以前那样光光盘就好些个,一不小心还又可能装错,实在也是一个大问题.现在好了基本上都是简单安装+网络升级先安装主要的后面如果需要什么在装什么?大大简化了流程.不行 ...
- uitableview 侧滑删除
https://github.com/MortimerGoro/MGSwipeTableCell
- [UOJ210]寻找罪犯
2-sat神题.. 告诉是2-sat我也完全想不到正解. 看了看题解其实一步步分析也不算很难 这个题首先是要围绕每个人是否是犯人和每句话是否是真话来思考 首先要明确的是: 1.好人不说谎话 2.说了谎 ...
- git代码提交与克隆
在工作中,越来越多的人会使用git来管理代码.下面简单的介绍一下git在工作中的使用流程 1.给你一个git地址,将代码拉下来基本操作流程如下: 1.1 git clone "项目地址&qu ...
- bzoj 1050: [HAOI2006]旅行comf(codevs.cn 1001 舒适的路线) 快排+并查集乱搞
没用的话:好像很久没发博客了,主要是懒太蒟找不到水题.我绝对没弃坑...^_^ 还用些话:本文为博主原创文章,若转载请注明原网址和作者. 进入正题: 先pa网址: bzoj :http://www.l ...
- EF Code-First 学习之旅 一对多的关系
public class Student { public Student() { } public int StudentId { get; set; } public string Student ...