React 路由
React 路由
路由器
React-Router 支持我们使用 HashRouter 和 BrowserRouter 两种路由规则,react-router-dom 提供了 BrowserRouter 和 HashRouter 两个组件来实现应用的 ui 和 url 同步
BrowserRouter 创建的 url 格式 http://xxx.com/path
HashRouter 创建的 url 格式 http://xxx.com/#/path
BrowserRouter
他是由 HTML5 提供的 history api 来保持 ui 和 url 同步的
1 | <BrowserRouter |
其中的参数如下:
bansename 所有的路由的基准 url,basename 的正确格式是前面有一个斜杠,但是尾部不能有斜杠
1 | <BrowserRouter basename="/calendar"> |
等同于
1 | <a href="/calendar/today" /> |
- forceRefresh 如果为 true,在导航过程中页面将会刷新一下,一般情况下只有在不支持 html5 history api 的浏览器中使用此功能
- getUserConfirmation 用于确认导航的函数,默认使用 window.confirm。例如当从/a 导航到/b 的时候,会默认使用 confirm 函数弹出一个提示,用户点击确定后才进行导航,否则不做任何处理。
1 | // 这是默认的确认函数 |
- keylength 用来设置 location.key 的长度
HashRouter
使用 url 的 hash 部分(window.loaction.hash)来保持 ui 和 url 的同步。由此可以看出,HashRouter 是通过 url 的 hash 属性来控制路由跳转的
1 | <HashRouter basename={string} getUserConfirmation={func} hashType={string} /> |
其中的参数如下:
- basename,getuserconfirmation 和 BrowserRouter 功能一样
- hashType.window.loaction.hash 使用的 hash 诶西,有如下几种
- slash - 后面跟一个斜杠,例如#/和#/sunshine/fuck
- noslash - 后面没有斜杠,例如#和#sunshine/fuck
- hashbang - 谷歌风格的 ajax crawlable ,例如#! 和#!/sunshine/fuck
Route
react-router 的工作方式是在组件树的顶层放一个 Router 组件,然后在组件树中散落着很多 Route 组件,顶层 Router 组件负责分析监听 url 的变化而 Route 组件可以直接读取这些信息。Router 与 Route 配合,Router 是“提供者”,Route 是“消费者”
Route 的基本使用
Route 是 React Route 用于配制路由信息的组件,也是 React Router 中使用频率最高的组件。每当一个组件需要根据 url 决定是否渲染时,就需要创建一个 Route
1 | <Route exact={bool} path={string} component={Component} /> |
其中的属性如下:
- exact:当 url 完全匹配时,值为 true,否则为 false,它控制匹配 / 路径时是否向下继续匹配
- path:构建嵌套路由时会使用到,每个 Route 都需要定一个 path 属性
- component:表示路径对应显示的组件
url 匹配到 Route 时,Route 会创建一个 match 对象作为 props 中的一个属性传递给被渲染的组件。这个对象包含以下四个属性
- params:Route 的 path 可以包含参数,params 就是用于从匹配到的 url 中解析出 path 中的参数
- isExact:同 Route 的 exact
- path:同 Route 的 path
- url:url 的匹配方式
Route 渲染组件的方式
component 属性
component 属性的值是一个组件,当 URL 和 Route 匹配时,component 属性定义的组件就会被渲染
1 | <Route path='/foo' component={Foo} > |
当 url 为/foo 的时候 Foo 组件被渲染
render(多用于权限验证)
render 的值是一个函数,他返回一个 React 元素,这种方式方便的为待渲染的组件传递额外的属性
1 | <Route |
Foo 组件接收到了额外的 data 属性
采用 render 方式渲染时,组件是否渲染不仅要看路径是否匹配,还要由 render 属性所接受的函数来共同决定。注意,此时 render 函数会接受一个参数 props,即当前 Route 组件的 props 对象。
children(多用于菜单)
children 的值也是一个函数,函数返回要渲染的 React 元素。与前两种方式的不同之处是,无论是否匹配成功,children 返回的组件都会被渲染。但是当匹配不成功的时候,match 属性为 null
1 | <Route |
如果 Route 匹配当前 URL,待渲染的元素的根节点 div 的 class 将设置成 active。
Switch
switch 通常用来包裹 Route,用来渲染路径匹配的第一个<Route>
或<Redirect>
,他里面不能放其他元素
例如不加<Switch>
1 | import { Route } from 'react-router-dom' |
Route 组件的 path 属性用于匹配路径,因为我们需要匹配/到 Home,匹配/login 到 Login,所以需要两个 Route,但是,我们不能这么写。这么写的话,当 url 的 path 为/login 的时候,会同时匹配到/和/login,因此页面会显示 Home 和 Login 两个组件,这个时候就需要 switch 来做到只展示一个匹配组件。
1 | import { Switch, Route } from "react-router-dom"; |
此时,再访问/login 的时候,却只显示了 Home 组件。这个时候就需要用到 exact 属性了,他的作用就是精确匹配路径,经常与 switch 联合使用,只有当 url 和该 route 的 path 属性完全一致的时候才能匹配上
1 | import { Switch, Route } from "react-router-dom"; |
link
在单页面应用中,往往需要在不同页面直接进行切换,这就使用到了 link 组件,link 组件为我们提供了一个声明式的,可访问的导航链接
1 | import { Link } from "react-router-dom"; |
- to:string | object:声明要导航到的链接地址,可以是一个字符串,也可以是一个对象
1 | import { Link } from 'react-router-dom' |
- Replace:boolean:该属性决定是将点击后的链接替换历史堆栈中的最新消息,设置为 true 的时候是替换,设置为 false 的时候是添加。默认为 false
1 | <Link to="/login" replace> |
navlink
navlink 是特殊的 link,可以与当前 url 匹配的 link 元素添加样式属性。
- activeclassname:string 表示当前元素处于激活状态时的类名,默认为 active
1 | import { NavLink } from "react-router-dom"; |
- activestyle:object 表示当前元素处于激活状态时的样式
1 | import { NavLink } from "react-router-dom"; |
- exact:boolean 设置为 true 时,当且仅当完全匹配时才应用 activeclassname 和 activestyle
1 | import { NavLink } from "react-router-dom"; |
- isactive:function 可以通过 isactive 添加一些额外的逻辑来决定当前链接是否处于激活状态
1 | import { NavLink } from 'react-router-dom' |
Redirect
路由重定向:
1 | <Switch> |
当请求/user/:id 被重定向去 /user/profile/:id
- 属性 from:string:需要匹配的将要被重定向路径
- 属性 to:string:重定向的 url 字符串
- 属性 to:object:重定向的 loaction 对象
- 数据 push:bool:若为真,重定向操作会把新地址加入到历史访问记录里面,并且无法回退到前面的页面
Promt
当用户离开当前页面做出一些提示,属性如下
- 属性 message:string 当用户离开当前页面时,设置的提示信息
1 | <Prompt message="确定要离开?" /> |
- 属性 message:func 当用户离开页面时,设置回调函数
1 | <Prompt message={(location) => `确定要去 ${location.pathname} ?`} /> |
- 属性 when:bool 决定是否启用 Prompt
嵌套路由
嵌套路由是指在 Route 渲染的组件内部定义新的 Route,比如上面的 login 组件中可以再定义两个路由
1 | const Login = ({match} => { |
注意:嵌套路由是基于当前路由创建的路由,前缀是我们当前的路由
动态路由
假设,再增加一个新的页面叫 Product,对应路径为/produc,但是只有用户登录了之后才显示。如果用静态路由,我们在渲染之前就确定了这条路由规则,这样即使用户没有登录,也可以访问 product,我们还不得不在 product 组件中做用户是否登录的检查
如果用动态路由,则只需要在代码中的一处涉及这个逻辑:
1 | <Switch> |
可以用任何条件决定 Route 组件是否渲染,比如可以根据页面的宽度,设备的类型来决定路由规则,动态路由就有了最大的自由度