react-router学习笔记

react-router是一种动态路由,而我们往常用的express中的路由为静态路由。

Link和NavLink的区别

在 v4 中,有两种方法可以将锚标签与路由集成:LinkNavLink

<NavLink><Link> 一样,但如果 <NavLink> 匹配浏览器的 URL,那么它可以提供一些额外的样式能力。例如:

1
2
3
4
5
6
7
8
9
10
const PrimaryHeader = () => (
<header className="primary-header">
<h1>Welcome to our app!</h1>
<nav>
<NavLink to="/app" exact activeClassName="active">Home</NavLink>
<NavLink to="/app/users" activeClassName="active">Users</NavLink>
<NavLink to="/app/products" activeClassName="active">Products</NavLink>
</nav>
</header>
)

使用 <NavLink> 可以让我给任何一个激活的链接设置一个 active 样式。而且,需要注意的是,我也可以给它们添加 exact 属性。如果没有 exact,由于 v4 的包容性匹配策略,那么在访问 /app/users 时,主页的链接将处于激活中。就个人经历而言,NavLinkexact属性等价于 v3 的 <link>,而且更稳定。

match.pathmatch.url的区别

到目前为止,props.match 对于知道详情页面渲染的 userId 以及如何编写我们的路由是很有用的。match 对象给我们提供了几个属性,包括 match.paramsmatch.pathmatch.url其他几个

起初这两者之间的区别似乎并不清楚。控制台日志有时会显示相同的输出,这使得它们之间的差异更加模糊。例如,当浏览器路径为 /users 时,它们在控制台日志将输出相同的值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const UserSubLayout = ({ match }) => {
console.log(match.url) // 输出:"/users"
console.log(match.path) // 输出:"/users"
return (
<div className="user-sub-layout">
<aside>
<UserNav />
</aside>
<div className="primary-content">
<Switch>
<Route path={match.path} exact component={BrowseUsersPage} />
<Route path={`${match.path}/:userId`} component={UserProfilePage} />
</Switch>
</div>
</div>
)
}

ES2015 概念: match 在组件函数的参数级别将被解构

虽然我们看不到差异,但 match.url 是浏览器 URL 中的实际路径,而 match.path 是为路由编写的路径。这就是为什么它们是一样的,至少到目前为止。但是,如果我们更进一步,在 UserProfilePage 中进行同样的控制台日志操作,并在浏览器中访问 /users/5,那么 match.url 将是 "/users/5"match.path 将是 "/users/:userId"

选择哪一个?

如果你要使用其中一个来帮助你构建路由路径,我建议你选择 match.path。使用 match.url 来构建路由路径最终会导致你不想看到的场景。下面是我遇到的一个情景。在一个像 UserProfilePage(当用户访问 /users/5 时渲染)的组件中,我渲染了如下这些子组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const UserComments = ({ match }) => (
<div>UserId: {match.params.userId}</div>
)
const UserSettings = ({ match }) => (
<div>UserId: {match.params.userId}</div>
)
const UserProfilePage = ({ match }) => (
<div>
User Profile:
<Route path={`${match.url}/comments`} component={UserComments} />
<Route path={`${match.path}/settings`} component={UserSettings} />
</div>
)

为了说明问题,我渲染了两个子组件,一个路由路径来自于 match.url,另一个来自 match.path。以下是在浏览器中访问这些页面时所发生的事情:

  • 访问 /users/5/comments 渲染 “UserId: undefined”。
  • 访问 /users/5/settings 渲染 “UserId: 5”。

那么为什么 match.path 可以帮助我们构建路径 而 match.url 则不可以呢?答案就是这样一个事实:{${match.url}/comments} 基本上就像和硬编码的 {'/users/5/comments'} 一样。这样做意味着后续组件将无法正确地填充 match.params,因为路径中没有参数,只有硬编码的 5

总的来说:

match:

  • path - (string) 用于匹配路径模式。用于构建嵌套的 <Route>
  • url - (string) URL 匹配的部分。 用于构建嵌套的 <Link>