本文小编为大家详细介绍“react怎么实现侧边栏联动头部导航栏效果”,内容详细,步骤清晰,细节处理妥当,希望这篇“react怎么实现侧边栏联动头部导航栏效果”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
项目中使用react+antd design+redux+react-reouter-dom
实现思路
编写路由表=》循环遍历路由表=》渲染侧边栏=》单击侧边栏获取相应的标签数据=》存入redux=》遍历循环redux数据渲染头部导航栏
路由表
const RouterTree = [
{
key: 'num_one',
title: {
icon: '',
text: 'text'
},
children: [
{
key: '1',
text: 'options1',
path: '/option1',
component: '',
isOutSide: true,
}
]
},
{
key: 'num_two',
title: {
icon: '',
text: 'text'
},
children: [
{
key: '2',
text: 'text',
path: '/option1',
component: '',
isOutSide: false
}
]
},
{
key: 'num_three',
title: {
icon: '',
text: 'text'
},
children: [
{
key: '3',
text: 'text',
path: '/option1',
component: '',
isOutSide: false
}
]
},
]
export default RouterTree
侧边栏渲染
引入路由表,循环遍历渲染侧边栏
import React, { Component } from 'react'
import { Menu } from 'antd';
import { NavLink as Link, withRouter } from 'react-router-dom'
import RouterTree from '@/modules/route.js'
render() {
const { activityKey } = this.state || {}
return (
<div>
<Menu
onClick={this.handleClick}
defaultSelectedKeys={['1']}
defaultOpenKeys={['sub1']}
selectedKeys={activityKey}
mode="inline"
inlineCollapsed={isToggle}
>
{RouterTree.map((item, index) => {
return (
<SubMenu
key={item.key}
title={item.title.text}
index={index}
>
{item.children && item.children.map((menuItem, menuIndex) => {
return (<Menu.Item
key={menuItem.key}
index={menuIndex}
>
{menuItem.isOutSide ? <a href="https://www.19jp.com">
由于单独使用redux不便,项目中引用react-redux,redux-thunk。
这里将侧边栏拆分为两个文件,一个是容器组件,一个为UI组件(以上的为UI组件)
容器组件(侧边栏)
容器组件为导出的组件,在容器组件中引入UI组件slide
import { connect } from 'react-redux'
import { business } from '@/tools/index.js'
import Slide from './slide'
const { processedArr } = business
const mapStoreToProps = (state) => {
const { dynamicJump,activityKey} = state || {}
let responseRoute = processedArr(dynamicJump)
return {
dynamicJump: [...responseRoute],
activityKey:activityKey
}
}
const mapDispatchToProps = (dispatch) => {
return {
updateRouter(item) {
dispatch((dispatch) => {
dispatch({
type: 'UPDATED_ROUTING', item: { ...item }
})
})
},
activityKeys(key){
dispatch((dispatch)=>{
dispatch({
type:'ACTIVITY_KEY',key:key
})
})
}
}
}
export default connect(mapStoreToProps, mapDispatchToProps)(Slide)
store
在src下新建一个store文件
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk';
import { routerMiddleware } from 'react-router-redux'
let createHistory = require('history').createBrowserHistory
let history = createHistory()
let routerWare = routerMiddleware(history)
const dynamicJump = {
dynamicJump: '这里设置默认值'(一般存放在session中),
activityKey: '这里设置默认值',
}
const reducers = function (state = dynamicJump, action) {
switch (action.type) {
case 'UPDATED_ROUTING':
state.dynamicJump =action.item
break;
case 'ACTIVITY_KEY':
if (action.key !== undefined) {
state.activityKey = action.key
}
break;
default:
break;
}
return { ...state }
}
const store = createStore(reducers, applyMiddleware(thunk, routerWare))
// 订阅事件
store.subscribe(() => {
let state = store.getState();
sessionStorage.setItem('dynamicJump',JSON.stringify(state.dynamicJump))
sessionStorage.setItem('activityKey',JSON.stringify(state.activityKey))
})
export default store
在根目录下将其注入进去(注意文件的引入位置)
import {Provider} from 'react-redux'
import store from './store/index.js'
ReactDOM.render(
<Provider store={store}><App /></Provider>,
document.getElementById('root')
);
头部导航栏
容器组件
import { connect } from 'react-redux'
import { push } from 'react-router-redux'
import { business } from '@/tools/index.js'
import Header from './head.jsx'
const { processedArr } = business
const mapStoreToProps = (state) => {
const { dynamicJump, activityKey } = state
let newRouteArr = processedArr(dynamicJump)
return {
dynamicJump: [...newRouteArr],
activityKey: activityKey
}
}
const mapDispatchToProps = (dispatch) => {
return {
removeKey(itemKey) {
dispatch((dispatch, getStore) => {
const { dynamicJump } = getStore() || {}
let removeArr = processedArr(dynamicJump)
const indexes = removeArr.findIndex((item) => item.key === itemKey)
// 点击头部导航条的删除(即删除保存在redux的数组元素即可)
if (removeArr.length > 1) {
removeArr.splice(indexes, 1)
}
// 删除之后跳转到删除元素的前一个元素的路由地址
let path = removeArr[indexes - 1] ? removeArr[indexes - 1].path : '/option1'
let keys = removeArr[indexes - 1] ? removeArr[indexes - 1].key : 0
if(keys===0){
keys=removeArr[0].key
}
dispatch({
type: 'UPDATED_ROUTING', item: { ...removeArr },
})
dispatch({
type: 'ACTIVITY_KEY', key: keys
})
// 这里进行跳转
dispatch(push(path))
})
},
changeActiveKey(key) {
dispatch((dispatch) => {
dispatch({
type: 'ACTIVITY_KEY', key: key
})
})
}
}
}
export default connect(mapStoreToProps, mapDispatchToProps)(Header)
这里存在着:如果删除头部组件的其中一个导航,那么需要跳转到该导航(删除的)的前一个路由地址,而这个操作在UI组件中是不方便的,这里我采取的方法是引入“history”模块(详细代码请移步到store.js),然后在容器组件中使用dispatch(push(path))跳转,也可以使用更为简单的方法,直接在容器组件中引入react-router的withRouter,包裹在最外层即:export default withRouter(connect(mapStoreToProps, mapDispatchToProps)(Header))
UI组件
render(){
const { dynamicJump } = this.props || {}
const { activeKey } = this.state || {}
<Tabs
hideAdd
onChange={this.onChange}
activeKey={activeKey}
type="line"
onEdit={this.onEdit}
className='tabs'
>
{ dynamicJump.map((item) => (
<TabPane tab={<Link to={item.path}>{item.text}</Link>} key={item.key} />
))}
</Tabs>
}
对于key值,可以使用react新增的钩子函数:getDerivedStateFromProps进行判断是否更行
static getDerivedStateFromProps(nextProps, preState) {
const { activityKey, dynamicJump } = nextProps || {}
const { activeKey } = preState || {}
if (activityKey !== activeKey) {
return {
activeKey: activityKey
}
}
return { allRoute: dynamicJump }
}
remove = targetKey => {
this.removeKey(targetKey)
}
removeKey(key) {
this.props.removeKey(key)
}