HOOKS
React Router附带了一些HOOK,可让您拜访路由器的状态并从组件外部执行导航
- useHistory
- useLocation
- useParams
- useRouteMatch
useHistory
useHistory 钩子返回 history 对象,能够应用 useHistory 进行导航
import { useHistory } from "react-router-dom";function HomeButton() { let history = useHistory(); function handleClick() { history.push("/home"); } return ( <button type="button" onClick={handleClick}> Go home </button> );}
useLocation
useLocation 钩子返回以后URL的 location 对象。能够把它设想成一个useState,每当URL发生变化时,它都会返回一个新的地位。
这是十分有用的,例如,当一个新的页面加载时,比方应用web剖析工具触发一个新的“页面视图”事件,如上面的例子所示:
import React from "react";import ReactDOM from "react-dom";import { BrowserRouter as Router, Switch, useLocation} from "react-router-dom";function usePageViews() { let location = useLocation(); React.useEffect(() => { ga.send(["pageview", location.pathname]); }, [location]);}function App() { usePageViews(); return <Switch>...</Switch>;}ReactDOM.render( <Router> <App /> </Router>, node);
useParams
useParams 动静参数列表的援用对象,用于获取<Route>
中的 match.params (动静参数)
import React from "react";import ReactDOM from "react-dom";import { BrowserRouter as Router, Switch, Route, useParams} from "react-router-dom";function BlogPost() { let { slug } = useParams(); return <div>Now showing post {slug}</div>;}ReactDOM.render( <Router> <Switch> <Route exact path="/"> <HomePage /> </Route> <Route path="/blog/:slug"> <BlogPost /> </Route> </Switch> </Router>, node);
useRouteMatch
useRouteMatch 尝试以与<Route>
雷同的形式匹配以后URL。它次要用于拜访匹配数据,而无需理论渲染<Route>
Now, instead of
import { Route } from "react-router-dom";function BlogPost() { return ( <Route path="/blog/:slug" render={({ match }) => { // Do whatever you want with the match... return <div />; }} /> );}
you can just
import { useRouteMatch } from "react-router-dom";function BlogPost() { let match = useRouteMatch("/blog/:slug"); // Do whatever you want with the match... return <div />;}
useRouteMatch 钩子也能够:
- 不承受任何参数并返回以后
<Route>
- 承受单个参数,与matchPath的props参数雷同。它能够是一个字符串模式的路径名(就像下面的例子),也能够是一个带有匹配道具的对象,像这样:
const match = useRouteMatch({ path: "/BLOG/:slug/", strict: true, sensitive: true});
<BrowserRouter>
Router
应用HTML5 History API((pushState, replaceState and the popstate event)来保障 UI 组件和 URL 同步
<BrowserRouter basename={optionalString} forceRefresh={optionalBool} getUserConfirmation={optionalFunc} keyLength={optionalNumber}> <App /></BrowserRouter>
basename <string>
基准URL,如果你的应用程序是从服务器上的子目录中提供的,你须要将其设置为子目录。一个正确格式化的basename应该有一个结尾斜杠,但没有结尾斜杠。
<BrowserRouter basename="/calendar"> <Link to="/today"/> // renders <a href="/calendar/today"> <Link to="/tomorrow"/> // renders <a href="/calendar/tomorrow"> ...</BrowserRouter>
getUserConfirmation <function>
用于确认路由跳转的函数。默认应用window.confirm
<BrowserRouter getUserConfirmation={(message, callback) => { // this is the default behavior const allowTransition = window.confirm(message); callback(allowTransition); }}/>
forceRefresh <boolean>
如果值为 true 路由跳转将会刷新整个页面。能够应用它来模仿传统服务器渲染应用程序,路由跳转之间刷新页面的工作形式
<BrowserRouter forceRefresh={true} />
keyLength <number>
location.key的长度。默认为6。
<BrowserRouter keyLength={12} />
children <element>
要渲染的子元素。
Note: 如果React < 16,必须应用单个子元素,因为render办法不能返回多个元素。如果您须要多个元素,则能够尝试将它们包装在extra中<div>
<HashRouter>
<Router>
应用 Hash 模式路由(i.e. window.location.hash)来保障 UI 组件和 URL 同步
重要阐明:Hash模式不反对location.key或location.state。在以前的版本中,咱们尝试对行为进行兼容解决,但存在无奈解决的极其状况。任何须要此行为的代码或插件都将无奈工作。因为此技术仅旨在反对旧版浏览器,因而咱们建议您配置服务器以供应用<BrowserHistory>
。
<HashRouter basename={optionalString} getUserConfirmation={optionalFunc} hashType={optionalString}> <App /></HashRouter>
basename <string>
基准URL,如果你的应用程序是从服务器上的子目录中提供的,你须要将其设置为子目录。一个正确格式化的basename应该有一个结尾斜杠,但没有结尾斜杠。
<HashRouter basename="/calendar"/><Link to="/today"/> // renders <a href="#/calendar/today">
getUserConfirmation <function>
用于确认路由跳转的函数。默认应用window.confirm
<HashRouter getUserConfirmation={(message, callback) => { // this is the default behavior const allowTransition = window.confirm(message); callback(allowTransition); }}/>
hashType <string>
window.location.hash 的编码类型。可用值:
- "slash" - 相似 #/ 或 #/sunshine/lollipops
- "noslash" - 相似 # 或 #sunshine/lollipops
- "hashbang" - 创立 “ajax crawlable”Hash (Google弃用) 相似 #!/ 或 #!/sunshine/lollipops
默认为"slash"。
children<element>
渲染单个子元素
<Link>
提供申明式、可拜访的导航。
<Link to="/about">About</Link>
to <string>
链接门路的字符串模式,由路由门路、搜寻参数和 Hash 属性形成
<Link to="/courses?sort=name" />
to <object>
具备以下属性:
- pathname:
<string>
示意要链接到的门路 - search:
<string>
查问参数 - hash: 一个放在URL中的Hash,例如 #a-hash.
- state: location.state 参数.
to <function>
将以后路由信息作为参数传递,该函数返回string或者object
<Link to={location => ({ ...location, pathname: "/courses" })} />
<Link to={location => `${location.pathname}?sort=name`} />
replace <boolean>
如果为 true,单击链接时将替换以后历史条目,而不是增加新条目
<Link to="/courses" replace />
innerRef <RefObject>
从React Router 5.1开始,如果您应用的是React 16,则不须要此性能,因为咱们会将ref转发到底层<a>
.应用一般的ref代替
应用React.createRef获取组件的底层援用。
component <React.Component>
如果须要应用自定义的导航组件,能够通过 component 指定
const FancyLink = React.forwardRef((props, ref) => ( <a ref={ref} {...props}>???? {props.children}</a>))<Link to="/" component={FancyLink} />
others
能够传递须要传递的参数,如title, id, className等。
<NavLink>
非凡的<Link>
,当它匹配以后URL时,它会为以后处于激活状态链接增加款式。
<NavLink to="/about">About</NavLink>
activeClassName <string>
元素处于活动状态时提供的class款式。默认的类名称是active。这将与className 连贯
<NavLink to="/faq" activeClassName="selected"> FAQs</NavLink>
activeStyle <object>
当元素处于活动状态时利用于元素的内联style款式。
<NavLink to="/faq" activeStyle={{ fontWeight: "bold", color: "red" }}> FAQs</NavLink>
strict <boolean>
如果为true,URL匹配时应用严格模式,门路的开端斜杠也会匹配。更多信息请参阅<Route strict>
文档
isActive <function>
用于增加额定的逻辑以确定链接是否活动状态。如果您想要做的不仅仅是验证链接的路径名与以后URL的路径名是否匹配,那么就应该应用这个办法。
<NavLink to="/events/123" isActive={(match, location) => { if (!match) { return false; } // only consider an event active if its event id is an odd number const eventID = parseInt(match.params.eventID); return !isNaN(eventID) && eventID % 2 === 1; }}> Event 123</NavLink>
location <object>
isActive个别用于比拟以后的历史地位(通常是以后浏览器的URL)。为了与不同的地位进行比拟,能够传递一个location
aria-current <string>
在流动链接上应用的 aria-current 属性的值。可用值:
- "page" - 用于指定一组分页链接中的链接
- "step" - 用于批示基于步骤的过程的步骤指示器中的链接
- "location" - 用于批示在视觉上高亮显示为流程图的以后组件的图像
- "date" - 用于批示日历中的以后日期
- "time" - 用于批示时间表中的以后工夫
- "true" - 用于批示导航链接是否处于活动状态
- "false" - 用于避免辅助技术对以后链接做出反馈(用例是在一个页面上阻止多个aria-current标签)
默认为 "page".
基于 WAI-ARIA 1.1 specifications
<Prompt>
从新导出外围提示符
<MemoryRouter>
非凡<Router>
,将URL的历史记录保留在内存中(不读取或写入地址栏)。在测试和非浏览器环境(如React Native)中很有用。
<MemoryRouter initialEntries={optionalArray} initialIndex={optionalNumber} getUserConfirmation={optionalFunc} keyLength={optionalNumber}> <App /></MemoryRouter>
initialEntries <array>
历史堆栈中的地位数组。这些对象能够是蕴含{pathname, search, hash, state}的残缺地位对象,也能够是简略的字符串url。
<MemoryRouter initialEntries={["/one", "/two", { pathname: "/three" }]} initialIndex={1}> <App /></MemoryRouter>
initialIndex <number>
initialEntries 数组中初始地位的索引。
getUserConfirmation <function>
用于确认导航的函数。当间接应用<MemoryRouter>和<Prompt>时,必须应用这个选项。
keyLength <number>
location.key的长度。默认为6。
children <element>
要渲染的子元素
Note: 如果React < 16,必须应用单个子元素,因为render办法不能返回多个元素。如果您须要多个元素,则能够尝试将它们包装在extra中<div>
<Redirect>
<Redirect>会导航到新地位。新地位将笼罩历史记录堆栈中的以后地位,就像服务器端重定向(HTTP 3xx)一样
<Route exact path="/"> {loggedIn ? <Redirect to="/dashboard" /> : <PublicHomePage />}</Route>
to <string>
要重定向到的URL。任何能够被 path-to-regexp@^1.7.0 辨认的无效URL门路,在to中应用的所有URL参数都必须由from笼罩
<Redirect to="/somewhere/else" />
to <object>
要重定向到的地位。pathname是能够被 path-to-regexp@^1.7.0 辨认的无效URL门路。
<Redirect to={{ pathname: "/login", search: "?utm=your+face", state: { referrer: currentLocation } }}/>
state对象能够通过this.props.location拜访。重定向到组件中的状态。这个新的援用键(它不是一个非凡的名称)而后将通过this.props.location.state拜访。由路径名'/ Login '指向的Login组件中的referrer
push <boolean>
<Redirect push to="/somewhere/else" />
如果为true,重定向会将新的条目推入历史记录,而不是替换以后条目
from <string>
要重定向的路径名。任何能够被 path-to-regexp@^1.7.0 辨认的无效URL门路。必须蕴含中应用的所有参数to。不应用的其余参数将to被疏忽。
Note: 仅当渲染的<Redirect>
外部时,能力用于匹配地位<Switch>
。请参阅<Switch children>
以获取更多详细信息。
<Switch> <Redirect from="/old-path" to="/new-path" /> <Route path="/new-path"> <Place /> </Route></Switch>// Redirect with matched parameters<Switch> <Redirect from="/users/:id" to="/users/profile/:id" /> <Route path="/users/profile/:id"> <Profile /> </Route></Switch>
exact <boolean>
齐全匹配;相当于Route.exact
NOTE: 当在<Switch>
中渲染<Redirect>
时,这只能与from一起应用,以准确匹配地位。参见<Switch children>
理解更多细节。
<Switch> <Redirect exact from="/" to="/home" /> <Route path="/home"> <Home /> </Route> <Route path="/about"> <About /> </Route></Switch>
strict <boolean>
严格的匹配;相当于Route.strict。
Note: 当在<Switch>
中渲染<Redirect>
时,它只能与from一起应用,以严格匹配地位。参见<<Switch children>
理解更多细节。
sensitive <boolean>
辨别大小写的匹配;相当于Route.sensitive。
<Route>
路由组件可能是React路由器中最重要的组件,须要了解和学习应用。它最根本的职责是在门路与以后URL匹配时渲染指定的UI组件。
想想以下代码:
import React from "react";import ReactDOM from "react-dom";import { BrowserRouter as Router, Route } from "react-router-dom";ReactDOM.render( <Router> <div> <Route exact path="/"> <Home /> </Route> <Route path="/news"> <NewsFeed /> </Route> </div> </Router>, node);
如果应用程序的URL门路是 '/',那么UI层次结构将是这样的:
<div> <Home /> <!-- react-empty: 2 --></div>
如果利用的地位是/news,那么UI层次结构将是:
<div> <!-- react-empty: 1 --> <NewsFeed /></div>
“React -empty” 正文只是React的null渲染的实现细节。但就咱们的目标而言,它是有启发意义的。一个路由在技术上总是被“渲染”的,即便它被渲染为null。当<Route>
的门路与以后URL匹配时,它就会渲染它的子组件(你的组件)。
如果同一个组件在组件树的同一点被用作多个<Route>
的子组件,React会将其视为同一个组件实例,并且在路由更改之间,组件的状态会被保留。如果不心愿这样做,那么在路由发生变化时,给每个路由组件增加一个惟一的key,将导致React从新创立该组件实例。
Route渲染办法
应用<Route>
来渲染内容的举荐办法是应用子元素,如上所示。不过,还有一些其余办法能够用来渲染<Route>
。提供这些性能次要是为了在引入钩子之前应用晚期版本的路由器构建应用程序。
<Route component>
<Route render>
<Route children>
function<Route>
中只能同时应用其中的一个形式,看看他们上面的解释,理解他们之间的区别。
Route属性
所有的<Route>
的渲染办法,都会传递三个参数
- match
- location
- history
component<Route>
匹配时渲染的 React 子组件。它将与route属性一起渲染
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);
当您应用component(而不是上面的render或children)时,路由器将应用React.createElement给定的组件创立一个新的React元素。这意味着,如果为component prop提供内联函数,则将在每个渲染器中创立一个新组件。这将导致现有组件的卸载和新组件的装置,而不仅仅是更新现有组件。当应用内联函数进行内联渲染时,请应用render或children道具(如下)。
render <function>
这样能够不便地进行内联渲染和包装,而无需进行上述不必要的重新安装。
而不是应用 component 创立一个新的React元素,传入门路匹配时调用的函数。render prop函数能够拜访所有与render prop组件雷同的路由道具(match, location , history)。
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);
Warning: <Route component>
优先于<Route render>
,所以不要在<Route>
中同时应用。
children <function>
有时须要判断渲染门路是否与路由门路匹配。在这种状况下,您能够应用children prop属性。它的工作原理完全相同,render不论是否有匹配
children 与 component, render 接管雷同的 match,location,history,除非路由不能匹配URL,否则match为空。容许依据路由是否匹配,来动静调整渲染UI组件。如果路由匹配,咱们会增加一个流动类
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);
对于动画也很有用:
<Route children={({ match, ...rest }) => ( {/* Animate will always render, so you can use lifecycles to animate its child in and out */} <Animate> {match && <Something {...rest}/>} </Animate> )}/>
Warning: <Route children>
优先于<Route component>
和<Route render>
,所以不要在同一个<Route
>中应用多个。
path < string | string[]>
任何能够被 path-to-regexp@^1.7.0 辨认的无效URL门路。
<Route path="/users/:id"> <User /></Route>
<Route path={["/users/:id", "/profile/:id"]}> <User /></Route>
没有path 始终匹配的路线。
exact <boolean>
仅当门路 location.pathname 齐全匹配时才匹配
<Route exact path="/one"> <About /></Route>
path | location.pathname | exact | matches? |
---|---|---|---|
/one | /one/two | true | no |
/one | /one/two | false | yes |
strict <boolean>
如果为true,带有尾斜杠的 path 将只与 location.pathname 带尾斜杠的路径名匹配,当在 location.pathname 中有额定的URL段时,这将不起作用
path | location.pathname | matches? |
---|---|---|
/one/ | /one | no |
/one/ | /one/ | yes |
/one/ | /one/two | yes |
Warning:能够应用strict来强制指定地位。pathname没有尾随斜杠,但为了做到这一点,strict和exact必须都为真
<Route exact strict path="/one"> <About /></Route>
path | location.pathname | matches? |
---|---|---|
/one/ | /one | yes |
/one/ | /one/ | no |
/one/ | /one/two | no |
location <object>
<Route>
元素尝试匹配 path 到以后的历史地位(通常是以后浏览器URL)。也能够传递 location,使不同的pathname进行匹配。
须要将<Route>
匹配到某个地位而不是以后历史地位时,这是十分有用的,如Animated Transitions示例所示
如果<Route>
元素被包裹在<Switch>
中,并且与传递给<Switch>
(或以后历史地位)的地位匹配,那么传递给<Route>
的 location 将被<Switch>
应用的 location 笼罩(这里给出)
sensitive <boolean>
当为true时,将匹配门路辨别大小写。
<Route sensitive path="/one"> <About /></Route>
path | location.pathname | sensitive | matches? |
---|---|---|---|
/one | /one | true | yes |
/One | /one | true | no |
/One | /one | false | yes |
<Router>
所有路由器组件的通用低级接口。通常,应用程序会应用一种高级路由器来代替:
<BrowserRouter>
<HashRouter>
<MemoryRouter>
<NativeRouter>
<StaticRouter>
应用低级别的
<Router>
常见用例是将自定义历史记录与状态治理库(例如Redux或Mobx)进行同步。请留神,不须要将状态治理库与 React Router 一起应用,仅用于深度集成。
import React from "react";import ReactDOM from "react-dom";import { Router } from "react-router";import { createBrowserHistory } from "history";const history = createBrowserHistory();ReactDOM.render( <Router history={history}> <App /> </Router>, node);
history <object>
用于导航的 history 对象
import React from "react";import ReactDOM from "react-dom";import { createBrowserHistory } from "history";const customHistory = createBrowserHistory();ReactDOM.render(<Router history={customHistory} />, node);
children <element>
要渲染的子组件
<Router> <App /></Router>
<StaticRouter>
永不扭转地位的<Router>
这在服务器端渲染场景中很有用,因为用户实际上并没有到处单击,所以地位实际上从未扭转。因而,它的名字是:static。在简略的测试中,当您只须要插入一个地位并对渲染输入作出断言时,它也很有用。
这是一个示例节点服务器,它为发送302状态代码,<Redirect>
并为其余申请发送惯例HTML:
import http from "http";import React from "react";import ReactDOMServer from "react-dom/server";import { StaticRouter } from "react-router";http .createServer((req, res) => { // This context object contains the results of the render const context = {}; const html = ReactDOMServer.renderToString( <StaticRouter location={req.url} context={context}> <App /> </StaticRouter> ); // context.url will contain the URL to redirect to if a <Redirect> was used if (context.url) { res.writeHead(302, { Location: context.url }); res.end(); } else { res.write(html); res.end(); } }) .listen(3000);
basename <string>
基准URL。basename 以 /
结尾,但没有结尾的 /
。
<StaticRouter basename="/calendar"> <Link to="/today"/> // renders <a href="/calendar/today"></StaticRouter>
location <string>
服务器接管的URL,可能req.url在节点服务器上
<StaticRouter location={req.url}> <App /></StaticRouter>
location <object>
相似 location 对象的 location 对象 同样具备{pathname, search, hash, state}
<StaticRouter location={{ pathname: "/bubblegum" }}> <App /></StaticRouter>
context <object>
JavaScript对象。在渲染过程中,组件能够向对象增加属性来存储无关渲染的信息。
const context = {}<StaticRouter context={context}> <App /></StaticRouter>
当<Route>
匹配时,它会把 context 对象传递给它渲染的 staticContext 组件。请查看服务器渲染指南,理解更多对于如何本人做这件事的信息。
渲染之后,能够应用这些属性来配置服务器的响应。
if (context.status === "404") { // ...}
children <element>
要渲染的子元素。
Note: 如果React < 16,必须应用单个子元素,因为render办法不能返回多个元素。如果您须要多个元素,则能够尝试将它们包装在extra中<div>
<Switch>
渲染胜利匹配 path 的第一个子元素<Route>
或<Redirect>
。
这与应用一堆<Route>
s有什么不同呢?
<Switch>
是惟一的,因为它只渲染一个<Route>
。相同,每一个匹配地位的<Route>
都会被蕴含。思考这些路线:
import { Route } from "react-router";let routes = ( <div> <Route path="/about"> <About /> </Route> <Route path="/:user"> <User /> </Route> <Route> <NoMatch /> </Route> </div>);
如果URL是/about
,则<About>
,<User>
和<NoMatch>
将全副渲染,因为它们都与门路匹配。这是设计好的,容许咱们以多种形式将<Route>
组合到咱们的应用程序中,比方侧边栏和面包屑,疏导选项卡等。
然而,有时咱们想只抉择一个<Route>
来渲染。如果 path 为/about
,并不想匹配/:user
(或者显示咱们的“404”页面)。上面是如何用Switch做到这一点:
import { Route, Switch } from "react-router";let routes = ( <Switch> <Route exact path="/"> <Home /> </Route> <Route path="/about"> <About /> </Route> <Route path="/:user"> <User /> </Route> <Route> <NoMatch /> </Route> </Switch>);
当初,如果 path 为/about
,<Switch>
将开始寻找匹配项<Route>
。将只匹配<Route path="/about" />
,并<Switch>
进行寻找匹配项和渲染<About>
等。同样,如果咱们在/michael
时,将只进行渲染<User>
。
location <object>
location对象,用于匹配子元素,而不是以后历史地位(通常是以后浏览器的URL)。
children <element>
<Switch>
的所有子元素都应该是<Route>
或<Redirect>
元素。只会渲染与以后path匹配的第一个子元素。
<Route>
元素应用它们的 path 属性来匹配,<Redirect>
元素应用它们的from 属性来匹配。没有path 属性的<Route>
或没有from 属性的<Redirect>
将始终匹配以后地位。
当在<Switch>
中蕴含<Redirect>
时,它能够应用<Route>
的任何 location 对象来匹配:path、exact和strict。from 只是 path 属性的别名。
将 location 属性提供给 <Switch>
,它会笼罩匹配子元素上的 location 属性
import { Redirect, Route, Switch } from "react-router";let routes = ( <Switch> <Route exact path="/"> <Home /> </Route> <Route path="/users"> <Users /> </Route> <Redirect from="/accounts" to="/users" /> <Route> <NoMatch /> </Route> </Switch>);
generatePath
能够应用generatePath函数生成路由的url。在外部应用path-to-regexp库。
import { generatePath } from "react-router";generatePath("/user/:id/:entity(posts|comments)", { id: 1, entity: "posts"});// Will return /user/1/posts
将门路编译为正则表达式的后果会被缓存,因而应用雷同的模式生成多条门路不会产生开销。
pattern <string>
generatePath 承受2个参数。第一个是作为Route组件的path属性提供。
params <object>
第二个参数是一个对象,它带有要应用的模式的相应参数。
如果提供的参数和门路不匹配,将抛出一个谬误:
generatePath("/user/:id/:entity(posts|comments)", { id: 1 });// TypeError: Expected "entity" to be defined
history
在本文档中,术语“history”和“history object”指的是 the history package,它是React路由器仅有的两个次要依赖项之一(除了React自身),它提供了在不同环境下用JavaScript治理会话历史的几种不同实现。
以下术语也会用到:
- “browser history” - 特定于DOM的实现,在反对HTML5 history API的Web浏览器中很有用
- “hash history” - 针对遗留web浏览器的特定于dom的实现
- “memory history” - 内存中的 history 实现,在测试和非dom环境(如React Native)中很有用
history 对象通常具备以下属性和办法:
- length
<number>
history 堆栈中的历史记录条目数 - action
<string>
以后操作(push,replace,pop) location
<object>
location 对象,具备以下属性:- pathname
<string>
URL门路 - search
<string>
URL查问字符串 - hash
<string>
URL Hash 片段 - state
<object>
特定于location的状态,例如push(path, state)在将该地位推入堆栈时所提供的状态。仅在浏览器和内存历史记录中可用。
- pathname
- push(path, [state])
<function>
将新条目推入历史记录堆栈 - replace(path, [state])
<function>
替换历史记录堆栈上的以后条目 - go(n)
<function>
将历史堆栈中的指针挪动n个条目 - goBack()
<function>
等同于 go(-1) - goForward()
<function>
等同于 go(1) - block(prompt)
<function>
避免导航(请参阅历史记录文档)
## history is mutable
history对象是可变的。因而,倡议从<Route>
的渲染属性中拜访 location,而不是从history.location中。这能够确保React的假如在生命周期钩子中是正确的。例如:
class Comp extends React.Component {componentDidUpdate(prevProps) { // will be true const locationChanged = this.props.location !== prevProps.location; // INCORRECT, will *always* be false because history is mutable. const locationChanged = this.props.history.location !== prevProps.history.location;}}<Route component={Comp} />;
依据您应用的实现,还可能呈现其余属性。更多细节请参考历史文档。
location
location 代表应用程序当初的门路,须要返回的门路,或者之前拜访过的门路。看起来像这样:
{ key: 'ac3df4', // not with HashHistory! pathname: '/somewhere', search: '?some=search-string', hash: '#howdy', state: { [userDefined]: true }}
路由器会在以下几个中央为你提供location对象:
- Route component as this.props.location
- Route render as ({ location }) => ()
- Route children as ({ location }) => ()
- withRouter as this.props.location
history 上也有记录。但不举荐应用,因为它是可变的。你能够在history doc中读到更多。
componentWillReceiveProps(nextProps) { if (nextProps.location !== this.props.location) { // navigated! }}
能够为导航的各个中央提供地位,而不是字符串:
- Web Link to
- Native Link to
- Redirect to
- history.push
- history.replace
通常只须要一个path 字符串,但如果须要增加一些额定的信息,在利用返回到那个特定地位时可用,你能够应用一个地位对象代替。如果你想要基于导航历史而不是门路(如模式)来划分UI分支,这是十分有用的
// usually all you need<Link to="/somewhere"/>// but you can use a location insteadconst location = { pathname: '/somewhere', state: { fromDashboard: true }}<Link to={location}/><Redirect to={location}/>history.push(location)history.replace(location)
最初,能够传递一个location 给以下组件:
- Route
- Switch
这将避免他们应用路由器状态中的理论地位。这对于动画和待定导航,或者任何时候你想让一个组件在一个不同于实在组件的地位渲染都是很有用的。
match
match对象蕴含了对于 <Route path>
如何匹配URL的信息。match对象蕴含以下属性
- params
<object>
从URL解析到的键/值对 - isExact
<boolean>
如果匹配整个URL(没有开端字符)则为true - path
<string>
用于匹配的path模式。用于构建嵌套的<Route>
s - url
<string>
URL的匹配局部。对于构建嵌套<Link>
s
能够在不同的中央拜访 match 对象:
- Route component as this.props.match
- Route render as ({ match }) => ()
- Route children as ({ match }) => ()
- withRouter as this.props.match
- matchPath as the return value
- useRouteMatch as the return value
如果 Route 中没有 path,因而总是进行匹配,将取得最靠近的父项匹配项。规定同样实用withRouter
null matches
应用children属性的<Route>
将调用其 children 函数,即便Route的 path 与以后 location 不匹配。在这种状况下,match将会是null。可能在<Route>
匹配时渲染的内容可能会很有用,然而这种状况会带来一些挑战。
“resolve” url的默认办法是退出 match.url 字符串到“relative” 门路。
let path = `${match.url}/relative-path`;
如果在 match 为null时尝试执行此操作,则最终会呈现TypeError。这意味着,当应用children属性时,尝试在<Route>
外部连贯“relative”门路是不平安的。
在生成空匹配对象的<Route>外部应用无门路<Route>时,会呈现相似但更奥妙的状况
// location.pathname = '/matches'<Route path="/does-not-match" children={({ match }) => ( // match === null <Route render={({ match: pathlessMatch }) => ( // pathlessMatch === ??? )} /> )}/>
没有path属性<Route>
s从其父对象继承匹配对象。如果其父匹配项为空,则其匹配项也将为空。这意味着
a)任何子路由/链接都必须是相对的,因为没有要解析的父级;
b)父级匹配能够为null的无门路路由须要应用应用children 属性进行渲染
matchPath
这使您能够应用与<Route>
雷同的匹配代码,除了失常渲染周期之外,例如在服务器上渲染之前收集数据依赖项。
import { matchPath } from "react-router";const match = matchPath("/users/123", { path: "/users/:id", exact: true, strict: false});
pathname
第一个参数是您想要匹配的路径名.如果您在服务器上应用Node。它会是req.path。
props
第二个参数是要匹配的props,它们与 Route 所承受的 match 属性雷同。它们与Route所承受的match 属性雷同。它也能够是一个字符串或字符串数组,作为{path}的快捷方式:
returns
当提供的 pathname 与 path 属性匹配时,它会返回一个对象
matchPath("/users/2", { path: "/users/:id", exact: true, strict: true});// {// isExact: true// params: {// id: "2"// }// path: "/users/:id"// url: "/users/2"// }
当提供的 pathname 与 path 属性不匹配时,它返回null。
matchPath("/users", { path: "/users/:id", exact: true, strict: true});// null
withRouter
非路由组件能够通过withRouter高阶组件拜访 History 对象的属性和进行<Route>
匹配。withRouter将在渲染时向包装组件传递更新的 match、location 和 history 属性。
{ path, // like /users/:id; either a single string or an array of strings strict, // optional, defaults to false exact, // optional, defaults to false}
import React from "react";import PropTypes from "prop-types";import { withRouter } from "react-router";// A simple component that shows the pathname of the current locationclass ShowTheLocation extends React.Component { static propTypes = { match: PropTypes.object.isRequired, location: PropTypes.object.isRequired, history: PropTypes.object.isRequired }; render() { const { match, location, history } = this.props; return <div>You are now at {location.pathname}</div>; }}// Create a new component that is "connected" (to borrow redux// terminology) to the router.const ShowTheLocationWithRouter = withRouter(ShowTheLocation);
重要提醒
withRouter 不订阅 location 更改,就像React Redux的connect订阅状态更改一样。而是在location 更改后从<Router>
组件流传进去,而后从新渲染。这意味着,withRouter它不会对route的扭转从新渲染,除非它的父组件从新渲染。
静态方法和属性
withRouter 包装组件的所有非特定于react的静态方法和属性都会主动复制到“connected”组件。
Component.WrappedComponent
被包装的组件作为动态属性公开,除其余事项外,该属性可用于隔离测试该组件。
// MyComponent.jsexport default withRouter(MyComponent)// MyComponent.test.jsimport MyComponent from './MyComponent'render(<MyComponent.WrappedComponent location={{...}} ... />)
wrapperComponentRef<function>
函数将作为ref道具传递给被包装的组件。
class Container extends React.Component { componentDidMount() { this.component.doSomething(); } render() { return ( <MyComponent wrappedComponentRef={c => (this.component = c)} /> ); }}
结语
更新于 2021.2.7