React项目生成路由
React项目生成路由
使用React-Router完成路由跳转
项目需要加入页面路由,具体需求是,点击左侧菜单栏的选项,在右侧空白部分根据路由渲染不同组件,并支持动态嵌套路由。
踩了一些坑,在一番尝试后完成,在此记录
完整项目demo放在了github上 github.com/bupt-yanch/Router-demo
一. 基本原理
- 注册路由以及对应组件。比如这里注册了四种不同的组件 exact表示精准路由匹配
<Router>
<Route path="/" exact component={Home}/>
<Route path="/smile" exact component={Smile}/>
<Route path="/settings" exact component={Settings}/>
<Route path="/settings/:id" exact component={RandomShow}/>
</Router>
- 在想要跳转的地方选用不同方法进行跳转
如果不带参数跳转,比如点击菜单选项,使用<Link/>进行跳转
<Menu defaultSelectedKeys={['1']} >
<Menu.Item key='1' icon={<HomeOutlined/>}>
Home
<Link to="/"/>
</Menu.Item>
<Menu.Item key='2' icon={<SmileOutlined/>}>
Smile
<Link to="/smile"/>
</Menu.Item>
<Menu.Item key='3' icon={<SettingFilled/>}>
Settings
<Link to="/settings"/>
</Menu.Item>
</Menu>
如果需要带参数进行跳转,就使用如下方法,被<HushRouter>包含的所有子组件可以调用this.props.history
const rand = Math.random();
this.props.history.push({
pathname: `/settings/${rand}`,
state: {
str: 'hello rand:',
rand: rand,
}
})
二. 根据历史记录正确选择Menu的Key
如果不做这个功能,在回退的时候,有可能路由和左侧菜单栏是不对应的。比如路由变为'/smile'的时候,左侧菜单栏高亮的选项还是Settings。
因为在回退的过程中,路由改变了,但Menu的key没改变。所以需要根据历史记录,监听其路由变化,并实时改变Menu的Key。
1. 添加state.menuKey
state = {
menuKey: ['1'],
};
2. 添加监听,并根据前缀匹配,更新state
componentDidMount() {
this.props.history.listen(route => {
const pathName = route.pathname;
console.log(pathName)
let key = '1';
if (pathName.startsWith("/smile")) {
key = '2';
} else if (pathName.startsWith("/settings")) {
key = '3';
}
this.setState({
menuKey: [key]
})
})
}
3. 设置Menu的key和state.menuKey关联
<Menu theme="dark"
defaultSelectedKeys={['1']}
mode="inline"
selectedKeys={this.state.menuKey}
>
三. 效果展示
启动服务后,默认渲染路由为 '/' 的组件

点击左侧不同的菜单Item,可以发现路由和右侧渲染内容都发生了改变

Settings组件中渲染的内容包括一个Button,是为了验证简单的嵌套路由。
点击这个按钮,会生成一个随机数,并在重定向到新路由时,将随机数加入新路由的路径中,且作为props传入新渲染的组件中

多次点击按钮,可以看到每次生成的随机数不同,对应的路由和渲染的内容不同


四. 后续优化
- 在使用动态路由后,路由传参跳转后刷新页面会导致白屏(参数消失,无法正常渲染)。参考了 博客链接 之后使用sessionStorage存储参数解决了这个问题。需要注意的是,如果传的参数是一个Json对象的话,需要转成String存,然后获取的时候parse,否则会无法正常存取。
// 比如某个组件的渲染就依赖跳转时传递的参数对象object,就可以如下编写
componentWillMount() {
const {location} = this.props;
let recvObject;
if (location.state && location.state.experiment) {
recvObject = location.state.object;
sessionStorage.setItem('object', JSON.stringify(recvObject));
} else {
recvObject = JSON.parse(sessionStorage.getItem('object'));
}
this.setState({
object: recvObject,
});
}

浙公网安备 33010602011771号