快来退出咱们吧!
"小和山的菜鸟们",为前端开发者提供技术相干资讯以及系列根底文章。为更好的用户体验,请您移至咱们官网小和山的菜鸟们 ( https://xhs-rookies.com/ ) 进行学习,及时获取最新文章。
"Code tailor" ,如果您对咱们文章感兴趣、或是想提一些倡议,微信关注 “小和山的菜鸟们” 公众号,与咱们取的分割,您也能够在微信上观看咱们的文章。每一个倡议或是同意都是对咱们极大的激励
前言
这节咱们将介绍 React
中 react - router
,路由跳转的配置以及应用
本文会向你介绍以下内容:
- 意识
react-router
react-router
根本应用react-router
高级应用react-router-config
意识 react - router
如果你是第一次接触 router 这个名词,能够先去这里补充一下本人的路由常识再来往下浏览哦
留神:以下内容基于 react-router v5 版本,如果和读者以后应用的不合乎,请以官网为主
装置 react-router
:
yarn add react-router-domnpm install react-router-dom
什么是 react-router
?
React Router is a set of navigation components that are combined with your application in a declarative manner. Whether you want to provide bookmarkable URLs for your web applications or use composable navigation methods in React Native, React Router can be used anywhere React renders
react-router
是一组以申明形式与您的应用程序组合的导航组件,换句话,react-router
是 React
体系中的路由库,它通过治理 URL,实现组件的切换和状态的变动
react-router 根本应用
React Router
中的组件次要分为三类:
路由器 BrowserRouter
和 HashRouter
BrowserRouter
应用惯例URL门路,创立一个像example.com/some/path
这样实在的 URL ,然而他们要求正确的配置服务器HashRouter
将以后地位存储在URL
的哈希局部中,因而URL
看起来相似于http://example.com/#/your/page
,因为哈希从不发送到服务器,因而这意味着不须要非凡的服务器配置
两者之间的次要区别是它们存储 URL
和与 Web
服务器通信的形式
路由匹配器,例如 Switch 和 Route:
当渲染 Switch
组件时,它将搜寻它的 Route
子元素,以查找门路与以后 URL
匹配的元素,它将出现找到的第一个 Route
并疏忽所有的其余路由。这意味着您应该将蕴含更多特定门路的 Route
放在不那么特定的路由之前
Switch
咱们来看上面的路由规定:
- 当咱们匹配到某一个门路时,咱们会发现有一些问题;
- 比方
/about
门路匹配到的同时,/:userid
也被匹配到了,并且最初的一个NoMatch
组件总是被匹配到;
<Route exact path="/" component={Home} /><Route path="/about" component={About} /><Route path="/profile" component={Profile} /><Route path="/:userid" component={User}/><Route component={NoMatch}/>
起因是什么呢?默认状况下,react-router
中只有是门路被匹配到的 Route
对应的组件都会被渲染;
然而理论开发中,咱们往往心愿有一种排他的思维:
- 只有匹配到了第一个,那么前面的就不应该持续匹配了;
- 这个时候咱们能够应用
Switch
来将所有的Route
进行包裹即可;
<Switch> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> <Route path="/profile" component={Profile} /> <Route path="/:userid" component={User} /> <Route component={NoMatch} /></Switch>
Route
它最根本的职责是在其门路与以后 URL 匹配时出现一些 UI
Route 的渲染办法一共有三类
- <Route component>
- <Route render>
- <Route children>
Route component
仅在地位匹配时依据 route props
渲染
import React from "react";import ReactDOM from "react-dom";import { BrowserRouter as Router, Route } from "react-router-dom";// All route props (match, location and history) are available to Userfunction User(props) { return <h1>Hello {props.match.params.username}!</h1>;}ReactDOM.render( <Router> <Route path="/user/:username" component={User} /> </Router>, node);
当你在应用此办法加载时,router
通常会依据给定的 component
去调用 React.createElement
创立一个新的 React
元素。这也就意味着如果你在此是用内联函数渲染的组件,那么它将会在每次渲染时都创立一个新的函数,即卸载组件装置新有组件,而不是更新。所以当你应用内联函数渲染组件时,请抉择 render
或 children
办法
Route render
你能够传入一个在地位匹配时调用的函数,而不是应用组件 prop
为您创立一个新的 React
元素
import React from "react";import ReactDOM from "react-dom";import { BrowserRouter as Router, Route } from "react-router-dom";// convenient inline renderingReactDOM.render( <Router> <Route path="/home" render={() => <div>Home</div>} /> </Router>, node);// wrapping/composing// You can spread routeProps to make them available to your rendered Componentfunction FadingRoute({ component: Component, ...rest }) { return ( <Route {...rest} render={routeProps => ( <FadeIn> <Component {...routeProps} /> </FadeIn> )} /> );}ReactDOM.render( <Router> <FadingRoute path="/cool" component={Something} /> </Router>, node);
须要留神的是:<Route component> 的优先级比 <Route render> 高,所以不要在同一个 Route
中同时调用两种办法
Route children
工作原理同 <Route render> ,只是无论是否匹配都会调用
import React from "react";import ReactDOM from "react-dom";import { BrowserRouter as Router, Link, Route} from "react-router-dom";function ListItemLink({ to, ...rest }) { return ( <Route path={to} children={({ match }) => ( <li className={match ? "active" : ""}> <Link to={to} {...rest} /> </li> )} /> );}ReactDOM.render( <Router> <ul> <ListItemLink to="/somewhere" /> <ListItemLink to="/somewhere-else" /> </ul> </Router>, node);
须要留神的是:<React children> 优先级比下面两个优先级都高
而这三种渲染形式都会传递雷同的 route props
- match :蕴含 <Route path> 如何匹配
URL
的信息 - location :代表应用程序当初所在的地位
- history : 用于在 JavaScript 中以各种形式治理会话历史记录
路由导航,例如:Link 、NavLink 、Redirect
<Link>
组件将在您的应用程序中创立链接。无论在何处出现<Link>
,锚点都将出现在HTML
文档中,而其最终会被渲染成a
元素NavLink
在Link
根底之上减少了一些款式属性,当其prop
与以后地位匹配时,能够给它设置一个activeClassName
(被选中) 的款式。- 任何时候要强制导航,你都能够应用
<Redirect>
,当出现<Redirect>
时,将依据prop
的to
值进行导航。
NavLink
门路选中时,对应的 a 元素变为红色
activeStyle
:沉闷时(匹配时)的款式;activeClassName
:沉闷时增加的 class;exact
:是否精准匹配;
<NavLink to="/" activeStyle={{color: "red"}}>home</NavLink><NavLink to="/about" activeStyle={{color: "red"}}>about</NavLink><NavLink to="/profile" activeStyle={{color: "red"}}>profile</NavLink>
然而,咱们会发现在选中 about
或 profile
时,第一个也会变成红色:
- 起因是/门路也匹配到了
/about
或/profile
- 这个时候,咱们能够在第一个
NavLink
中增加上exact
属性
<NavLink exact to="/" activeStyle={{ color: 'red' }}> home</NavLink>
默认的 activeClassName
:
- 事实上在默认匹配胜利时,
NavLink
就会增加上一个动静的active class
; - 所以咱们也能够间接编写款式
a.active { color: red;}
当然,如果你放心这个 class
在其余中央被应用了,呈现款式的层叠,也能够自定义 class
<NavLink exact to="/" activeClassName="link-active">home</NavLink><NavLink to="/about" activeClassName="link-active">about</NavLink><NavLink to="/profile" activeClassName="link-active">profile</NavLink>
Redirect
Redirect
用于路由的重定向,当这个组件呈现时,就会执行跳转到对应的 to
门路中,而 Redirect
最常见的场景即鉴权
- 用户浏览器输出
User
界面url
; - 若用户未登录,需重定向到登录页面。若已登录,则可进入
User
界面
App.js
中提前定义好 Login
页面对应的 Route
:
<Switch> ...其余Route <Route path="/login" component={Login} /> <Route component={NoMatch} /></Switch>
在 User.js
中写上对应的逻辑代码:
import React, { PureComponent } from 'react'import { Redirect } from 'react-router-dom'export default class User extends PureComponent { constructor(props) { super(props) this.state = { isLogin: false, } } render() { return this.state.isLogin ? ( <div> <h2>微信公众号:小和山的菜鸟们</h2> <h2>用户名: Coder tailor</h2> </div> ) : ( <Redirect to="/login" /> ) }}
react-router 高级应用
嵌套路由
此示例显示嵌套路由的工作原理。路由 /topics
加载 Topics
组件,该组件依据门路 :id
值有条件地出现任何进一步的 <Route>
。
import React from "react";import { BrowserRouter as Router, Switch, Route, Link, useRouteMatch, useParams} from "react-router-dom";export default function App() { return ( <Router> <div> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/about">About</Link> </li> <li> <Link to="/topics">Topics</Link> </li> </ul> <Switch> <Route path="/about"> <About /> </Route> <Route path="/topics"> <Topics /> </Route> <Route path="/"> <Home /> </Route> </Switch> </div> </Router> );}function Home() { return <h2>Home</h2>;}function About() { return <h2>About</h2>;}function Topics() { let match = useRouteMatch(); return ( <div> <h2>Topics</h2> <ul> <li> <Link to={`${match.url}/components`}>Components</Link> </li> <li> <Link to={`${match.url}/props-v-state`}> Props v. State </Link> </li> </ul> {/* Topics 页面有本人的 <Switch>,其中蕴含更多基于 /topics URL 门路 的路由。您能够将此处的第二个 <Route> 视为所有主题的“索引”页面,或者 未抉择主题时显示的页面 */} <Switch> <Route path={`${match.path}/:topicId`}> <Topic /> </Route> <Route path={match.path}> <h3>Please select a topic.</h3> </Route> </Switch> </div> );}function Topic() { let { topicId } = useParams(); return <h3>Requested topic ID: {topicId}</h3>;}
动静路由
当咱们探讨动静路由时,咱们是指在您的利用渲染时产生的路由,而不是在运行中的利用之外配置或约定的。
这意味着简直所有内容都是 React Router
中的一个组件。上面是对该 API
的回顾,以理解其工作原理:
首先,为您要定位的环境获取一个 Router
组件,并将其出现在应用程序的顶部。
// react-dom (what we'll use here)import { BrowserRouter } from "react-router-dom";ReactDOM.render( <BrowserRouter> <App /> </BrowserRouter>, el);const App = () => ( <div> <nav> <Link to="/dashboard">Dashboard</Link> </nav> <div> <Route path="/dashboard" component={Dashboard} /> </div> </div>);
该 Route
将出现 <Dashboard {... props} />
,其中 props
是路由器特定的货色,比方 { match, location, history }
。如果用户不在 / dashboard
上,则 Route
将出现 null
。
react-router-config
路由配置的形式多种多样,让咱们看一下来自官网的最佳实际
// 路由配置只是数据// React 十分善于将数据映射到组件中,而 <Route> 是一个组件.//咱们的路由配置只是一个带有 path 和 component props 的逻辑"路由"数组//排序形式与你在 `<Switch>` 中的程序雷同。//路由配置const routes = [ { path: "/sandwiches", component: Sandwiches }, { path: "/tacos", component: Tacos, routes: [ { path: "/tacos/bus", component: Bus }, { path: "/tacos/cart", component: Cart } ] }];
嵌入 App 中
export default function App() { ReactDOM.render( <Router> <div> <ul> <li> <Link to="/tacos">Tacos</Link> </li> <li> <Link to="/sandwiches">Sandwiches</Link> </li> </ul> <Switch> {routes.map((route, i) => ( <RouteWithSubRoutes key={i} {...route} /> ))} </Switch> </div> </Router> ,document.getElementById('root') )}
组件在这儿
function Sandwiches() { return <h2>Sandwiches</h2>;}function Tacos({ routes }) { return ( <div> <h2>Tacos</h2> <ul> <li> <Link to="/tacos/bus">Bus</Link> </li> <li> <Link to="/tacos/cart">Cart</Link> </li> </ul> <Switch> {routes.map((route, i) => ( <RouteWithSubRoutes key={i} {...route} /> ))} </Switch> </div> );}function Bus() { return <h3>Bus</h3>;}function Cart() { return <h3>Cart</h3>;}//<Route> 的非凡包装器,它晓得如何通过将"子"路由//传递到它出现的组件的 `routes` 属性来解决它们。function RouteWithSubRoutes(route) { return ( <Route path={route.path} render={props => ( // pass the sub-routes down to keep nesting <route.component {...props} routes={route.routes} /> )} /> );}
下节预报
本节咱们学习了 React-Router
中高阶组件以及组件补充的内容,至此,React 相干常识咱们已学习结束,下一节咱们将为之前的留言板加上登录性能!