react-router v4 多层路由嵌套问题

react-router升级到了v4版本,原来V3的嵌套路由如下,但是V4里面,根据官方的Switch还是父子组件的写法还是弄不出来,不知道如何弄了,请教各位,多谢了。

V3的路由如下,比如为router.jsx,页面总共3层路由,比如/app/dashboard/index,其中Page和App组件通过{this.props.children}调用后就可以显示子组件了。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Router, Route, hashHistory, IndexRedirect } from 'react-router';
import Page from './components/Page';
import Dashboard from './components/dashboard/Dashboard';
import ReactJavascript from './components/js/ReactJavascript';
import Angular from './components/js/Angular';
import Vue from './components/js/Vue';
import Php './components/backend/Php';
import Golang from './components/backend/Golang';
import Python from './components/backend/Python';
import Centos from './components/system/Centos';
import Ubuntu from './components/system/Ubuntu';
import Suse from './components/system/Suse';

const routes =
    <div>
        <Route path={'/'} component={Page}>
            <IndexRedirect to="/app/dashboard/index" />
            <Route path={'app'} component={App}>
                <Route path={'js'}>
                    <Route path={'react'} component={ReactJavascript} />
                    <Route path={'angular'} component={Angular} />
                    <Route path={'vue'} component={Vue} />
                </Route>
                <Route path={'backend'}>
                    <Route path={'php'} component={Php} />
                    <Route path={'golang'} component={Golang} />
                    <Route path={'python'} component={Python} />
                </Route>
                <Route path={'system'}>
                    <Route path={'centos'} component={Centos} />
                    <Route path={'ubuntu'} component={Ubuntu} />
                    <Route path={'suse'} component={Suse} />
                </Route>
                <Route path={'dashboard/index'} component={Dashboard} />
            </Route>
        </Route>;
    </div>

ReactDOM.render(
    <Router history={hashHistory}>
        {routes}
    </Router>,
    document.getElementById('root')
);

Update:V4的代码如下,但是还是跑不通,并且发现url里的锚点#没有了,比如正常的url是127.0.0.1/#/app/dashboard/index,现在变成127.0.0.1/app/dashboard/index,强行添加#也不行,直接跳转到127.0.0.1/app/dashboard/index

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { Router, Route, IndexRedirect, Switch, Redirect, BrowserRouter } from 'react-router-dom';
import createHashHistory from 'history/createBrowserHistory'
import Page from './components/Page';
import Dashboard from './components/dashboard/Dashboard';
import ReactJavascript from './components/js/ReactJavascript';
import Angular from './components/js/Angular';
import Vue from './components/js/Vue';
import Php './components/backend/Php';
import Golang from './components/backend/Golang';
import Python from './components/backend/Python';
import Centos from './components/system/Centos';
import Ubuntu from './components/system/Ubuntu';
import Suse from './components/system/Suse';
const history = createHashHistory();

const Routes = () => (
    <Switch>
        <Route path='/' component={ () => <Redirect to='/app/dashboard/index' component={ Page } />  } />
        <Route exact path='/app' component={ App } />
        <Route exact path='/app/js/react' component={ ReactJavascript } />
        <Route exact path='/app/js/angular' component={ Angular } />
        <Route exact path='/app/js/vue' component={ Vue } />
        <Route exact path='/app/backend/php' component={ Php } />
        <Route exact path='/app/backend/golang' component={ Golang } />
        <Route exact path='/app/backend/python' component={ Python } />
        <Route exact path='/app/system/centos' component={ Centos } />
        <Route exact path='/app/system/ubuntu' component={ Ubuntu } />
        <Route exact path='/app/system/suse' component={ Suse } />
    </Switch>
)
        

ReactDOM.render(
    <Router history={history}>
        <Routes />
    </Router>,
    document.getElementById('root')
);

Page组件的代码如下。

import React from 'react';

class Page extends React.Component {
    render() {
        return (
            <div style={{height: '100%'}}>
                {this.props.children}
            </div>
        )

    }
}

export default Page;

App组件的代码如下。

import React, { Component } from 'react';
import { Layout } from 'antd';
const { Content, Footer } = Layout;
import './style/index.less';
import SiderCustom from './components/SiderCustom';   //这里面就是通过Menu组件构造的3级导航菜单了,通过Link指向路由
import HeaderCustom from './components/HeaderCustom';

class App extends Component {
    state = {
        collapsed: false,
    };
    toggle = () => {
        this.setState({
            collapsed: !this.state.collapsed,
        });
    };
    render() {
        return (
            <Layout className="ant-layout-has-sider">
              <SiderCustom path={this.props.location.pathname} collapsed={this.state.collapsed} />
              <Layout>
                <HeaderCustom toggle={this.toggle} />
                <Content style={{ margin: '0 16px', overflow: 'initial' }}>
                  {this.props.children}
                </Content>
                <Footer style={{ textAlign: 'center' }}>
                  React-router v4
                </Footer>
              </Layout>
            </Layout>
        );
    }
}

export default App;
阅读 21.9k
3 个回答

1、先来说#的问题,V4表示这个锅我不背,要#那肯定是hashHistory,那么你是如下用的:

import createHashHistory from 'history/createBrowserHistory'
 应该是
import createHashHistory from 'history/createHashHistory'

2、 路由嵌套的问题,你可以查看我如下的回答,或者查看react-router有关路由嵌套

我的回答: https://segmentfault.com/q/10...

官方示例: https://reacttraining.com/rea...

v4中,route已经不再被直接允许进行嵌套,通常的做法是,将子route放入到route对应的组件内部

看了下你的代码,写错了吧。
router.js怎么会直接挂载到root上呢?这个是App.js做的。
我给你改下,你看看,看看行不行,然后不懂的再问下。
Router.js

import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { Router, Route, hashHistory, IndexRedirect, Switch, Redirect } from 'react-router-dom'
import Page from './components/Page'
import Dashboard from './components/dashboard/Dashboard'
import ReactJavascript from './components/js/ReactJavascript'
import Angular from './components/js/Angular'
import Vue from './components/js/Vue'
import Php './components/backend/Php'
import Golang from './components/backend/Golang'
import Python from './components/backend/Python'
import Centos from './components/system/Centos'
import Ubuntu from './components/system/Ubuntu'
import Suse from './components/system/Suse'

export default () => (
    <Switch>
        <Route path='/' component={ () => <Redirect to='/app/dashboard/index' component={ Page } />  } />
        <Route exact path='/app' component={ App } />
        <Route exact path='/app/js/react' component={ ReactJavascript } />
        <Route exact path='/app/js/angular' component={ Angular } />
        <Route exact path='/app/js/vue' component={ Vue } />
        <Route exact path='/app/backend/php' component={ Php } />
        <Route exact path='/app/backend/golang' component={ Golang } />
        <Route exact path='/app/backend/python' component={ Python } />
        <Route exact path='/app/system/centos' component={ Centos } />
        <Route exact path='/app/system/ubuntu' component={ Ubuntu } />
        <Route exact path='/app/system/suse' component={ Suse } />
    </Switch>
)

App.js

import React, { Component } from 'react'
import { Route, Switch, HashRouter } from 'react-router-dom'
import { Layout } from 'antd'
const { Content, Footer } = Layout
import './style/index.less'
import SiderCustom from './components/SiderCustom'   //这里面就是通过Menu组件构造的3级导航菜单了,通过Link指向路由
import HeaderCustom from './components/HeaderCustom'

// *************
//把router引入 V4倡导所有的路由都是DOM
import MainFrame from './Router'
// *************


class App extends Component {
    state = {
        collapsed: false
    }
    toggle = () => {
        this.setState({
            collapsed: !this.state.collapsed,
        })
    }
    render() {
        return (
            <Layout className="ant-layout-has-sider">
              <SiderCustom path={this.props.location.pathname} collapsed={this.state.collapsed} />
              <Layout>
                <HeaderCustom toggle={this.toggle} />
                <Content style={{ margin: '0 16px', overflow: 'initial' }}>
                {
                  //放这里,把App挂载到root里
                }
                <MainFrame />
                </Content>
                <Footer style={{ textAlign: 'center' }}>
                  React-router v4
                </Footer>
              </Layout>
            </Layout>
        )
    }
}

ReactDOM.render(
    <HashRouter>
      <Switch>
        <App />
      </Switch>
    </HashRouter>,
  document.getElementById('root')
)

Page.js
这个不需要了,已经在router.js中引入,如果style有问题,自己看看修改一下

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题