参考资料
React Router中的组件
- React Router中的组件主要分为3类,他们都从react-router-dom中获取到:
- 路由器组件:
<BrowserRouter>
和<HashRouter>
- 路线匹配器组件:
<Route>
和<Switch>
- 导航组件:
<Link>
,<NavLink>
和<Redirect>
- 路由器组件:
路由器组件
- 每个React Router应用程序的核心应该是路由器组件。
- 对于Web项目,react-router-dom提供
<BrowserRouter>
和<HashRouter>
路由器。两者之间的主要区别是它们存储URL和与Web服务器通信的方式。 <BrowserRouter>
使用常规的URL路径。这些通常是外观最好的URL,但是它们要求正确配置服务器。具体来说,您的Web服务器需要在所有由React Router客户端管理的URL上提供相同的页面。Create React App在开发中即开即用地支持此功能,并附带有关如何配置生产服务器的说明。<HashRouter>
将当前位置存储在URL 的hash一部分中,因此URL看起来像http://example.com/#/your/page。由于哈希从不发送到服务器,因此这意味着不需要特殊的服务器配置。- 要使用 路由器组件,只需确保将其呈现在元素层次结构的根目录下即可。
使用方法
- 通常会在src-index.js中将顶级
<App>
元素包装在路由器组件中,如下所示: - 然后在src-APP.js中使用路线匹配器组件
路线匹配器组件
- 路线匹配器组件:
<Route>
和<Switch>
<Route>
组件
<Route>
组件:定义路由组件。- path属性:(字符串)匹配路径,没有定义 path 的
<Route>
总是会被匹配。 - exact属性:(可省略属性值)表示准确匹配路径。如不使用该属性,则默认是模糊匹配path。如果为 true,则只有在 path 完全匹配
location.pathname
时才匹配。 - 渲染方式的属性见下方,一般选component属性。其他更多属性可参考官网
- path属性:(字符串)匹配路径,没有定义 path 的
渲染方式(<Route>
属性)
<Route>
组件渲染方式(在不同的情况下使用不同的方式,只使用一种即可):- component属性:(组件)路径匹配成功后渲染的组件。【优先使用该属性】
- 指定只有当位置匹配时才会渲染的 React 组件,该组件会接收 route props 作为属性。具体使用方法可见下方。
- render属性:(函数)在该路径下渲染的内容
- 使用 render 可以方便地进行内联渲染和包装,而无需进行上文解释的不必要的组件重装。可以传入一个函数,以在位置匹配时调用,而不是使用 component 创建一个新的 React 元素。render 渲染方式接收所有与 component 方式相同的 route props。(使用方法参考官网)
- 警告:
<Route component>
优先于<Route render>
,因此不要在同一个<Route>
中同时使用两者。
- children属性:(函数)在该路径下渲染的内容
- 有时候不论 path 是否匹配位置,你都想渲染一些内容。在这种情况下,你可以使用 children 属性。除了不论是否匹配它都会被调用以外,它的工作原理与 render 完全一样。
- 使用方法可参考官网
- 警告:
<Route component>
优先于<Route render>
优先于<Route children>
,因此不要在同一个中同时使用多个。
- component属性:(组件)路径匹配成功后渲染的组件。【优先使用该属性】
- 三种渲染方式都将提供相同的三个路由属性:match、location、history
使用方法
<Route>
组件应在<Switch>
内部,他们都应该在路由器组件内部作为子元素存在。- 方法1:如果你已经在src-index.js中使用路由器组件包裹App组件,那么可以在src-App.js中使用
<Route>
组件:- 注意:路由器组件中始终包含
<header/>
组件。 - 这意味着如果应用程序的位置是
/
,那么 UI 的层次结构将会是:<header /><Home />
。 - 或者,如果应用程序的位置是
/detail/1
(1可以是任意id值),那么 UI 的层次结构将会是:<header /><Detail />
- 注意:路由器组件中始终包含
- 方法2:页可以直接在src-index.js中的路由器组件内部使用
<Route>
组件。
<Switch>
组件
<Switch>
组件用于渲染与路径匹配的第一个子<Route>
或<Redirect>
。<Switch>
组件工作原理:- 当**
<Switch>
被渲染时,它会搜索其子元素<Route>
组件,以查找路径与当前URL匹配的元素。当它找到一个时,它将渲染那个<Route>
并且忽略所有其他的<Route>
组件**。 - 这意味着应该将具有更特定(通常更长的)路径的
<Route>
放在不太特定的路径之前。 - 如果没有
<Route>
匹配,<Switch>
将不呈现任何内容(null)。
- 当**
- 总结:
<Switch>
路由中的Switch 代表只匹配一个路由,如果不使用<Switch>
嵌套,路由会多次匹配。
例子
在src-index.js中:
1 | import React from "react"; |
注意:<Route path>
匹配的是URL的开头,而不是整个URL。
因此,<Route path="/">
将始终与URL匹配。
因此,我们通常把这个<Route>
放在<Switch>
的最后。
另一种可能的解决方案是使用<Route exact path="/">
,它准确匹配整个URL。
导航组件
- 导航组件:
<Link>
,<NavLink>
和<Redirect>
<Link>
组件
<Link>
组件:类似于 <a>
标签(最终也会被渲染为 a 标签)。
1 | import { Link } from 'react-router-dom'; |
- to 属性:可理解为 a 标签的 href属性。
- 属性值可以是一个字符串形式的链接地址,通过 pathname、search 和 hash 属性创建:
<Link to='/courses?sort=name' />
- 也可以是对象形式的链接地址,可以具有以下任何属性:
- pathname:要链接到的路径
- search:查询参数
- hash:URL 中的 hash,例如
#the-hash
- state:存储到 location 中的额外状态数据
- 属性值可以是一个字符串形式的链接地址,通过 pathname、search 和 hash 属性创建:
replace属性: 布尔值,当设置为 true 时,点击链接后将替换历史堆栈中的当前条目,而不是添加新条目。默认为 false。
1
<Link to="/courses" replace />
innerRef属性: 函数,允许访问组件的底层引用。(类似普通组件的ref属性)
1
2
3
4
5const refCallback = node => {
// node 指向最终挂载的 DOM 元素,在卸载时为 null
}
<Link to="/" innerRef={refCallback} />
<NavLink>
组件
一个特殊版本的 <Link>
,它会在与当前 URL 匹配时为其呈现元素添加样式属性。
1 | import { NavLink } from 'react-router-dom'; |
activeClassName属性: string,当元素处于激活状态时应用的类,默认为 active。它将与 className 属性一起使用。
1
<NavLink to="/faq" activeClassName="selected">FAQs</NavLink>
activeStyle属性: object,当元素处于激活状态时应用的样式。
1
2
3
4
5
6const activeStyle = {
fontWeight: 'bold',
color: 'red'
};
<NavLink to="/faq" activeStyle={activeStyle}>FAQs</NavLink>exact属性: bool,默认为false,如果为 true,则只有在位置完全匹配时才应用激活类/样式。
1
<NavLink exact to="/profile">Profile</NavLink>
strict属性: bool,默认为false,如果为 true,则在确定位置是否与当前 URL 匹配时,将考虑位置的路径名后面的斜杠。有关更多信息,请参阅
文档 。1
<NavLink strict to="/events/">Events</NavLink>
isActive属性: func
添加额外逻辑以确定链接是否处于激活状态的函数。如果你要做的不仅仅是验证链接的路径名与当前 URL 的路径名相匹配,那么应该使用它。1
2
3
4
5
6
7
8
9
10
11// 只有当事件 id 为奇数时才考虑激活
const oddEvent = (match, location) => {
if (!match) {
return false;
}
const eventID = parseInt(match.params.eventID);
return !isNaN(eventID) && eventID % 2 === 1;
}
<NavLink to="/events/123" isActive={oddEvent}>Event 123</NavLink>
location: objectisActive 属性:默认比较当前历史位置(通常是当前的浏览器 URL)。你也可以传递一个不同的位置进行比较。
<Redirect>
组件 重定向
使用 <Redirect>
会导航到一个新的位置。新的位置将覆盖历史堆栈中的当前条目,例如服务器端重定向(HTTP 3xx)。
使用<Link>
类似<a>
,需要点击才能跳转,而使用 <Redirect>
会直接导航到一个新的位置。
to属性: string
要重定向到的 URL,可以是 path-to-regexp 能够理解的任何有效的 URL 路径。所有要使用的 URL 参数必须由 from 提供。1
<Redirect to="/somewhere/else" />
to属性: object
要重定向到的位置,其中 pathname 可以是 path-to-regexp 能够理解的任何有效的 URL 路径。上例中的 state 对象可以在重定向到的组件中通过 this.props.location.state 进行访问。而 referrer 键(不是特殊名称)将通过路径名 /login 指向的登录组件中的 this.props.location.state.referrer 进行访问。
路由传值
- 在 react 中 有两种方式进行路由传值:
- 方法1:通过动态路由传值(占位符)。类似于
/a/:id/:value
。在组件内部可使用this.props.match.params.xxxx
来获取所传参数值。【推荐使用该方法,因为可以获取所传参数值】- 例子:
- 在src-App.js中,定义路由匹配的路径时使用动态路由传值:符合要求就跳转Detail组件。
- detail-index.js中,使用
this.props.match.params.id
获取所传参数值,并将其传给action: - detail-store-actionCreators.js中, action根据路径中获取到的id进行不同的AJAX请求,后端接受AJAX请求后根据不同地址返回不同数据给客户端:
- 例子:
- 方法2:通过 原始的 GET 路径后面,添加
?key=value
的方式。在 组件内部 可使用this.props.location.search
的方式获取键值对(只不过获取过后还是一个字符串,需要进一步的解析才能获取所传参数值)
- 方法1:通过动态路由传值(占位符)。类似于
- 补充:node中使用querystring获取
?
后的参数可直接得到json格式对象
子路由的嵌套
API 钩子
注意:以下钩子只能在 函数组件 的内部调用。
useRouteMatch()
- useRouteMatch()尝试以与
<Route>
相同的方式匹配当前URL。它主要用于在不实际呈现<Route>
的情况下访问匹配数据。 - 获取的match对象包含的属性见下方补充。
- 例子:
补充:Route组件的match属性(对象)
- Route组件的match属性
- 一个match对象包含有关如何信息
<Route path>
相匹配的URL。match对象包含以下属性:- params -(对象)从与路径的动态段相对应的URL解析的键/值对
- isExact-(布尔值)true如果整个URL都匹配(没有结尾字符)
- path-(字符串)用于匹配的路径模式。用于构建嵌套
<Route>
- url-(字符串)URL的匹配部分。用于构建嵌套
<Link>
- path和url的区别可参考这篇文章
useParams()
- useParams将返回URL参数的键/值对的对象。使用它来访问当前
<Route>
的match.params。 - 例子: