您的位置:首页 > Web前端 > React

react(ant-design-pro)路由-router踩坑

2018-08-18 09:06 4801 查看

最近学习react,使用的是阿里推出的ant-design-pro框架,踩了一些关于react(ant-design)路由的坑,在此做一下总结。

router

我们先大致了解一下react和ant-design-pro中的路由。

首先我们来讲一下React中原生的路由(router)的实现方式:

是以路由标签嵌套的形式,把路径(path)和对应要渲染的组件(component)以属性的形式指定在路由标签中,即可配置好路由。

React.render((
<Router>
<Route path="/" component={App}>
{/* 当 url 为/时渲染 Dashboard */}
<IndexRoute component={Dashboard} />
<Route path="about" component={About} />
<Route path="inbox" component={Inbox}>
<Route path="messages/:id" component={Message} />
</Route>
</Route>
</Router>
), document.body)

在github( https://github.com/reactjs/react-router-tutorial/tree/master/lessons )上有详细的react的router的教程,但是教程是比较早的了,思路差不多,可以作为参考。

然后再看ant-design-pro中的路由:

 

const routerConfig = {
'/': {
component: dynamicWrapper(app, ['user', 'login'], () => import('../layouts/BasicLayout')),
},
'/dashboard/analysis': {
component: dynamicWrapper(app, ['chart'], () => import('../routes/Dashboard/Analysis')),
},
'/dashboard/monitor': {
component: dynamicWrapper(app, ['monitor'], () => import('../routes/Dashboard/Monitor')),
},
}

ant-design-pro把路由配置这个过程封装了一遍,我们需要做的就是在src/common/router.js文件下,写一份如上代码的路由配置数据,ant-design-pro会把这些配置信息转化成react原生的路由标签,从而实现路由。

ant-design-pro中写路由配置数据的问题

antd-pro的对路由配置数据有一个模糊检索的机制,通常我们写一个类似于/dashboard/analysis的路径,毫无疑问,我们在浏览器打开 */dashboard/analysis 可以正常访问到该路径对应的路由;但如果我们输入了一个没有在路由中定义的、此路径的子路径,antd会先查找该路径,没有查找到就会向上路径匹配,即*/dashboard/analysis 。也就是说,如果我们在路由配置中写的是 */dashboard/analysis,且我们在浏览器打开的路径是 */dashboard/analysis/test,但是实际效果是只会显示*/dashboard/analysis 路径对应的页面。

同时这个机制还有一个副作用:

当定义的路由是*/dashboard/analysis,没有以"/"结尾,antd的路由机制会始终认为 */dashboard/analysis是最末端的路径,即我们再到路由中定义一个*/dashboard/analysis/page1,然后我们到浏览器去访问 */dashboard/analysis/page1,它会因为上述机制,始终会指向 */dashboard/analysis这个路径。也就是说,我们要想在某个路径中继续写它的子路径,我们必须以"/"结尾,形如 */dashboard/analysis/ ,否则会因为antd-pro的这个机制,不渲染其子路由。

 

路由的跳转

pathname、history

关于路由的跳转问题,普遍是以 <Link>标签,和事件触发 两种方式来进行的:

Link标签: <Link to={{ pathname : ' /sort ' , query : { name : 'sunny' }}}> 点击跳转 </Link> 

事件:this.props.history.push({ pathname : '/sort' ,query : { name: ' sunny'} })

值得注意的是,我在网上看到的资料,pathname这个属性名写的是path,但是经过我的测试发现使用path并不能实现跳转,还会报错:Warning: Hash history cannot PUSH the same path; a new entry will not be added to the history stack

而用pathname就可以解决这个问题;

其次,使用事件触发的方式,要使用this.props.history.push,而网上的很多说法是写this.props.router.push,这样写会报错:router为undefined。

withRouter

在摸索react路由的过程中,还碰到一个问题:在子组件中想要触发跳转事件时,我按上述的history写了一个点击事件,点击后执行this.props.history.push({pathname:'/xxx'}),但是出现了报错,说history未定义。在网上搜索后找到了一个合适的解决方法:

先在子组件中引入withRouter: import { withRouter } from "react-router-dom";

然后在子组件export导出时,用withRouter将组建包裹起来: withRouter(ChildComponent)

这样即可使得子组件的props属性也带上了history方法。

 

路由的传参、取参

Params

第一种形式是将参数直接挂在url的后面,用"/"隔开,但是我们再定义路由之前就要把这个参数约定好,形如 /sort/:id,这里的id可以看做一个占位符,当我们跳转到形如 /sort/5的路径时,我们会转到参数id=5对应的页面。

此时我们可以通过params来获取参数。这个时候又碰到坑了:

网上的资料大多数是说通过this.props.params.id即可取到参数id的值,但是我实际操作过程中,显示params为undefined。于是我把this.props在控制台打印出来,看到其中包含了form,history,location,match,routerData,staticContext,逐个点开发现,我们需要的params竟然在match里面!

也就是说,要取得路由形式为/sort/:id的参数,实际上是通过 this.props.match.params.id取到的,关于这个问题被很多网上的答案误导了。

query

第二种传参形式就是在写跳转链接的时候,将路径和参数以对象的形式写在一起,如:{ pathname : '/sort' ,query : { name: ' sunny'}}。

这样的形式传递的参数,是不会显示在url中的,并且在刷新页面的时候,参数会丢失,(类似于post传参)。

当我们第一次跳转到*/sort页面的时候,可以通过  this.props.location.query  取到query中输入的参数。

值得注意的是,经过我的测试后发现,query这个键名可以任意命名,例如"aaa",之后在跳转到的页面通过 this.props.location.aaa也可以获取到参数。

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: