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 User
function 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 rendering
ReactDOM.render(
<Router>
<Route path="/home" render={() => <div>Home</div>} />
</Router>,
node
);
// wrapping/composing
// You can spread routeProps to make them available to your rendered Component
function 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 instead
const 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 location
class 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.js
export default withRouter(MyComponent)
// MyComponent.test.js
import 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