react-router4路由嵌套问题

发布于 2022-09-06 00:03:35 字数 144 浏览 11 评论 0

clipboard.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

戈亓 2022-09-13 00:03:35

我没有使用这种方式(Route里面再次嵌套路由方式),因为这种方式不好(感觉路由被耦合了),所以我还是分离出来一个组件,这样每个路由所在的组件直接嵌套到里面就OK了,如下:

router/index.js

<Router>
            <Switch>
                <Route exact path="/account/register" component={Register}/>
                <Route exact path="/account/login" component={Login}/>
                <Route exact path="/email/verify/:token" component={VerifyEmail}/>
                <Route exact path="/" component={Index}/>
                <Route exact path="/explore" component={Explore}/>
                <Route exact path="/user" component={User}/>
                <Route exact path="/mysites" component={MySites}/>
                <Route component={NoMatch}/>
            </Switch>
    </Router>

Layout.js

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import classNames from 'classnames';
import Topbar from '../components/layout/Topbar'
import Sidebar from '../components/layout/Sidebar'

import {Route,withRouter} from 'react-router-dom'

import {getUserInfo} from '../utils'
import VerifyEmailDlg from './Dialog/VerifyEmailDlg'
import SitesSidebar from '../components/layout/SitesSidebar'
import {connect} from 'react-redux';

import {setBodyWidth,setIsMySites,setSidebar} from '../actions'

const styles = theme => ({
    root: {
        width: '100%',
        height: '100%',
        zIndex: 1,
        overflow: 'hidden',
    },
    appFrame: {
        display: 'flex',
        width: '100%',
        height: '100%',
    },
    content: {
        position: 'absolute',
        top: '56px',
        right: 0,
        left: 0,
        bottom: 0,
        marginLeft:0,
        flexGrow: 1,
        boxSizing:'border-box',
        backgroundColor: '#fff',
        padding:0,
        transition: theme.transitions.create('margin', {
            easing: theme.transitions.easing.sharp,
            duration: theme.transitions.duration.leavingScreen,
        }),
        height: 'calc(100% - 56px)'
    },
    contentShift: {
        marginLeft: '240px',
        transition: theme.transitions.create('margin', {
            easing: theme.transitions.easing.easeOut,
            duration: theme.transitions.duration.enteringScreen,
        }),
    },
});
class Layout extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            showVerifyEmailDig:false,
            user:null
        };
    }
    componentWillMount(){
        //this.showVerifyEmailDialog();
        window.addEventListener('resize', this.resizeListener);
        this.resizeListener();
        this.routerChanged(this.props.location.pathname);
    }
    componentWillUnmount(){
        window.removeEventListener('resize', this.resizeListener);
    }
    //监听路由变化
    routerChanged(pathname){
        if (pathname.indexOf('mysites')!=-1){
            this.props.dispatch(setIsMySites(true));
        }else{
            this.props.dispatch(setIsMySites(false));
        }
    };
    resizeListener=()=> {
        let bodyWidth = document.body.offsetWidth;
        this.props.dispatch(setBodyWidth(bodyWidth));
    };
    showVerifyEmailDialog=()=>{
        let that = this;
        getUserInfo(function(isLogin,user){
            if (isLogin&&user.is_active==0){
                that.setState({
                    showVerifyEmailDig:true,
                    user:user
                })
            }
        });
    };
    render() {
        const { classes,width,showSiteSidebar,sideBarInfo } = this.props;

        return (
                <div className={classes.root}>
                    <VerifyEmailDlg
                        onClose={()=>{
                            this.setState({
                                showVerifyEmailDig:false
                            })
                        }}
                        showVerifyEmailDig={this.state.showVerifyEmailDig}
                        user={this.state.user}/>
                    <div className={classes.appFrame}>
                        <Topbar showSearchBar={width>1024}/>
                        <Sidebar/>
                        {showSiteSidebar ? <SitesSidebar/>:null}
                        <main className={classNames(classes.content,((showSiteSidebar||sideBarInfo.open)&&width>1024) && classes.contentShift)}>
                            {this.props.children}
                        </main>
                    </div>
            </div>

        );
    }
}

const mapStateToProps = state => {
    return {
        column:state.layout.column,
        width:state.layout.bodyWidth,
        sideBarInfo:state.layout.sideBarInfo,
        showSiteSidebar:state.layout.showSiteSidebar,
        isMySites:state.layout.isMySites
    }
};

export default withRouter(connect(mapStateToProps)(withStyles(styles)(Layout)));

我这里只展示出Index组件,其它的因为跟它差不多我就不展示了,如下

Index.js

import React from 'react'
import PropTypes from 'prop-types';
import {withStyles} from 'material-ui/styles'
import classNames from 'classnames'
import Grid  from 'material-ui/Grid';
import AppBar from 'material-ui/AppBar'
import Tabbar from '../components/Tabbar'
import Layout from '../components/Layout'

import {connect} from 'react-redux';

function TabContainer(props) {
    return <div style={{ padding: 20 }}>{props.children}</div>;
}

class Index extends React.Component{
    constructor(props){
        super(props);
        this.state={
            tabIndex:0,
        }
    }
    onTabChanged=(index)=>{
        this.setState({ tabIndex: index });
    };
    render(){
        const { classes,column } = this.props;
        const tabs = [{ id:1,name:'关注者动态' },{ id:2,name:'我的动态' },{ id:3,name:'全部动态' }];

        return(
            <Layout>
                <Grid container spacing={0} justify={'center'}>
                    <Grid item xs={12}>
                        <AppBar position="static" color="default" className={classNames(classes.appBar)}>
                            <Grid container spacing={0} justify={'center'}>
                                <Grid item xs={column}>
                                    <Tabbar
                                        tabs={tabs}
                                        onTabChanged={this.onTabChanged}
                                        index={this.state.tabIndex} />
                                </Grid>
                            </Grid>
                        </AppBar>
                    </Grid>
                    <Grid item xs={column}>
                        {this.state.tabIndex === 0 && <TabContainer>sdfsf                    </TabContainer>}
                        {this.state.tabIndex === 1 && <TabContainer>{'Item Two'}</TabContainer>}
                        {this.state.tabIndex === 2 && <TabContainer>{'Item Three'}</TabContainer>}
                    </Grid>
                </Grid>
            </Layout>
        )
    }
}

const mapStateToProps = state => {
    return {
        column:state.layout.column
    }
};

const styles = theme =>({
    appBar: {
        boxShadow:'none !important'
    },
});
export default connect(mapStateToProps)(withStyles(styles)(Index))
夏の忆 2022-09-13 00:03:35

访问的路由的是什么?

如若梦似彩虹 2022-09-13 00:03:35

react-router 用的路由匹配库是path-to-regexp

实际上你这里要匹配的不是根,而是任意二级路径。你可以把path写成

'/([^/.]+)'

并且加上exact

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文