react(ant-design-pro)路由-router踩坑
最近学习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也可以获取到参数。
阅读更多- 基于React+Router+Redux+Sagas+fetch+ant Design +less + es6+mockjs的项目过程总结
- react-router v4 路由规则解析
- Ant Design of React—第七节
- React学习笔记——Router(有待完善类比学习、页面路由与服务端路由部分)
- Ant Design of React—第八节
- 开发你的第一个React + Ant Design网页(一、配置+编写主页)
- 深入理解 react-router 路由系统
- 详解react-router4 异步加载路由两种方法
- 基于WebStorm, React和Ant.Design开发WebAppDemo
- react入门篇 ant-design
- 【开发】Cordova+Ant Design+React教程
- React-router v4 路由配置方法小结
- react-router路由传值
- react-router路由配置
- React第三方组件1(路由管理之Router的使用②多层级跳转及重定向)
- React-router 4路由嵌套
- react-router v4 使用 history 控制路由跳转
- react+webpack+wepack-dev-server的环境中ant design图标离线的方法
- 记一次ant design pro配置axios代理
- react-router 父子路由同时要接收 params 的写法