react-router(v4)
概要
开发单页应用, 首先绕不开的内容就是路由, react router v4 版本是最新的版本. 和之前的版本相比, 成熟了很多, 也简单了很多, 使用起来更加方便.
核心 component
react-router v4 可以用于 web 和 native. 这里主要讨论基于 web 的应用.
react-router 有很多 components, 但是只要掌握下面 3 个 component 就可以管理好 react 应用的路由了.
router component
router 是整个应用的路由. 在 web 应用中, 使用 browerrouter 来包装 app
<browserrouter> <app /> </browserrouter>
然后, 在 app component 中, 就可以使用 route 来定义各个路由对应的 component
route component
每个 route 都是一个具体的路由, 对应一个具体的页面. route 可以对应一个 component, 也可以直接写个匿名的 render 函数.
route 中最常用的属性就是 path, 也就是路由的地址, 除此之外, route 最重要的作用是会将 { match, location, history } 3 个属性注入到对应的 component 或者 render 函数中.
link component
link 是用来导航的, 也就是在不同 route 之间切换就会用到 link.
常用路由示例
示例工程
示例工程的创建采用 create-react-app 工具.
$ create-react-app route-test $ cd route-test $ yarn add react-router-dom
基本使用
修改工程中的 app.js 文件, 增加 route 的 sample
import react, { component } from 'react' import { browserrouter as router, route, link } from 'react-router-dom' import './app.css' const index = () => <h2>home</h2> const about = () => <h2>about</h2> const users = () => <h2>users</h2> class app extends component { render() { return ( <router> <div> <nav> <ul> <li> <link to="/">home</link> </li> <li> <link to="/about/">about</link> </li> <li> <link to="/users/">users</link> </li> </ul> </nav> <route path="/" exact component={index} /> <route path="/about/" component={about} /> <route path="/users/" component={users} /> </div> </router> ) } } export default app
这个示例中, 就包含了 3 个常用组件 router, route 和 link
路由参数
路由的参数可以加在 path 上, 下面的示例中, users component 可以通过注入的 match 来得到 url 中的参数.
import react, { component } from 'react' import { browserrouter as router, route, link } from 'react-router-dom' import './app.css' const index = () => <h2>home</h2> const about = () => <h2>about</h2> const users = ({ match }) => ( <h2> user is {match.params.name}, age: {match.params.age} </h2> ) class app extends component { render() { return ( <router> <div> <nav> <ul> <li> <link to="/">home</link> </li> <li> <link to="/about/">about</link> </li> <li> <link to="/users/test/16">users</link> </li> </ul> </nav> <route path="/" exact component={index} /> <route path="/about/" component={about} /> <route path="/users/:name/:age" component={users} /> </div> </router> ) } } export default app
query 参数
除了上面那种 restful 的参数方式, 也可以通过 query 来传递参数. 下例中, 通过 location.search 来获取 querystring, 至于解析 querystring, 已有很多现成的方法可以使用.
import react, { component } from 'react' import { browserrouter as router, route, link } from 'react-router-dom' import './app.css' const index = () => <h2>home</h2> const about = ({ match, location }) => ( <h2>about's search string: {location.search}</h2> ) const users = ({ match }) => ( <h2> user is {match.params.name}, age: {match.params.age} </h2> ) class app extends component { render() { return ( <router> <div> <nav> <ul> <li> <link to="/">home</link> </li> <li> <link to={{ pathname: '/about/', search: '?name=test&age=16' }}> about </link> </li> <li> <link to="/users/test/16">users</link> </li> </ul> </nav> <route path="/" exact component={index} /> <route path="/about/" component={about} /> <route path="/users/:name/:age" component={users} /> </div> </router> ) } } export default app
faq
在刚开始使用 react-router 时, 可能会有些疑问, 我整理了自己在使用中一些疑惑:
match 是如何注入到 component 中的
match, location, history 这 3 个 object, 是由 route component 作为 props 注入到它的 render 方法, 或者 component={xxx} prop 对应的组件中的
match.path 和 match.url 有什么区别
- match.path 是用来做匹配用的, 也就是在 route 中使用的
- match.url 是用来迁移页面用的, 也就是在 link 中使用的
比如上面的例子中, 对于 /users
- match.path 是 users:name/:age
- match.url 是 /users/test/16
和 有什么区别
- browserrouter 是用于和 server 有交互的 router
- hashrouter 是用于静态文件服务的 router
和 的区别
当有多个 route 并列时, 如果外层没有包裹 switch, 那么匹配到的 route 都会被 render, 如果有 switch, 那么只会 render 第一个匹配上的 route
route 如果不设置 path, 则每次都会匹配成功
和 的区别
navlink 是一种特殊的 link, 它可以设置一些 active 时的样式.
路由信息和 redux 状态管理如何结合
路由信息本质上也是一种状态信息, 放不放在 redux 中来管理, 相信很多人都会纠结. 官方的建议是不要把路由的状态放在 redux 的 store 中来管理, 理由如下:
- 路由状态一般只有 components 才关心, 不管放不放在 redux 中, component 的代码不会有什么改变
- 大部分情况下, 路由跳转都是通过 link, navlink, redirct 来完成, 如果需要通过代码, 或者异步 action 中来跳转, 可以通过传入 history 对象来完成.
- 路由变化一般不需要通过时间旅行(time travel, redux 的一个调试工具)来 debug.