持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情
专栏说明:对于react-router v6版本,有同事反应缺少相对完整的中文文档,查看不方便。为了便于使用,作者对官网文档进行针对性翻译,便于v6版本更广泛的被使用。
<Link>
类型定义:
declare function Link(props: LinkProps): React.ReactElement;
interface LinkProps
extends Omit<
React.AnchorHTMLAttributes<HTMLAnchorElement>,
"href"
> {
replace?: boolean;
state?: any;
to: To;
reloadDocument?: boolean;
}
type To = Partial<Location> | string;
内置元素 <Link>
是用于通过点击跳转页面的。 在 react-router-dom
中,<Link>
会渲染一个<a>
标签, 标签的 href
为Link的 to
属性. 也就是说,右键点击一个 <Link>
也是起作用的. 你也可以这么写:<Link reloadDocument>
, 以此来阻止浏览器默认事件。
使用案例:
import * as React from "react";
import { Link } from "react-router-dom";
function UsersIndexPage({ users }) {
return (
<div>
<h1>Users</h1>
<ul>
{users.map((user) => (
<li key={user.id}>
<Link to={user.id}>{user.name}</Link>
</li>
))}
</ul>
</div>
);
}
<Link to>
的 to
参数,如果不是以 /
开头的话,表示是一个相对路由。路径中可能会包含 ..
来检索上一级,类似目录指令的 cd
。
在 React Native 中使用:
类型定义:
declare function Link(props: LinkProps): React.ReactElement;
interface LinkProps extends TouchableHighlightProps {
children?: React.ReactNode;
onPress?(event: GestureResponderEvent): void;
replace?: boolean;
state?: any;
to: To;
}
<Link>
用于响应用户点击后跳转其他的 View
, 渲染为一个 <a>
标签。 在 react-router-native
, 中, <Link>
渲染一个 TouchableHighlight
。可以使用TouchableHighlight
配置项来自定义样式和行为。
import * as React from "react";
import { View, Text } from "react-native";
import { Link } from "react-router-native";
function Home() {
return (
<View>
<Text>Welcome!</Text>
<Link to="/profile">Visit your profile</Link>
</View>
);
}
<NavLink>
类型定义:
declare function NavLink(
props: NavLinkProps
): React.ReactElement;
interface NavLinkProps
extends Omit<
LinkProps,
"className" | "style" | "children"
> {
caseSensitive?: boolean;
children?:
| React.ReactNode
| ((props: { isActive: boolean }) => React.ReactNode);
className?:
| string
| ((props: {
isActive: boolean;
}) => string | undefined);
end?: boolean;
style?:
| React.CSSProperties
| ((props: {
isActive: boolean;
}) => React.CSSProperties);
}
<NavLink>
是特殊类型的<Link>
, 可以记录 "active" 状态。 可用于面包屑或者菜单的选中点亮。对于用户和读者来说也提供了上下文的导航说明。
默认的, <NavLink>
激活时,会加上类名active
,v5中也是这么做的. 不同的是,新版本v6.0.0-beta.3
中属性移除了 activeClassName
和 activeStyle
,取而代之的是 style
或者 className
属性,用于自定义行内样式或者自定义类名,当然也可以穿一个函数作为属性给 <NavLink>
组件来自定义行为。
例子:
import * as React from "react";
import { NavLink } from "react-router-dom";
function NavList() {
// This styling will be applied to a <NavLink> when the
// route that it links to is currently selected.
let activeStyle = {
textDecoration: "underline",
};
let activeClassName = "underline";
return (
<nav>
<ul>
<li>
<NavLink
to="messages"
style={({ isActive }) =>
isActive ? activeStyle : undefined
}
>
Messages
</NavLink>
</li>
<li>
<NavLink
to="tasks"
className={({ isActive }) =>
isActive ? activeClassName : undefined
}
>
Tasks
</NavLink>
</li>
<li>
<NavLink to="tasks">
{({ isActive }) => (
<span
className={
isActive ? activeClassName : undefined
}
>
Tasks
</span>
)}
</NavLink>
</li>
</ul>
</nav>
);
}
如果你很熟悉 v5 的 API,可以二次封装一下使用:
import * as React from "react";
import { NavLink as BaseNavLink } from "react-router-dom";
const NavLink = React.forwardRef(
({ activeClassName, activeStyle, ...props }, ref) => {
return (
<BaseNavLink
ref={ref}
{...props}
className={({ isActive }) =>
[
props.className,
isActive ? activeClassName : null,
]
.filter(Boolean)
.join(" ")
}
style={({ isActive }) => ({
...props.style,
...(isActive ? activeStyle : null),
})}
/>
);
}
);
end
属性用于控制不会级联点亮。如果想要只在完全匹配路由是active,而不是在该路由上几级路径都被active,可以使用这个属性。下面的例子,只会在路径为 /
时匹配 active,其他任何路径都不会点亮:
<NavLink to="/" end>
Home
</NavLink>
<Navigate>
类型定义:
declare function Navigate(props: NavigateProps): null;
interface NavigateProps {
to: To;
replace?: boolean;
state?: any;
}
<Navigate>
被渲染时,会立即改变当前的location. 和hooks useNavigate
可以达到一样的效果,传递的参数也一样。
提示:
<Navigate>
可以在不能使用路由 hooks 的地方代替 useNavigate
下面的例子中,会先拿到登录状态的user,若没有user,渲染登录表单;如果拿到了登录信息,则通过<Navigate>
直接跳转到 dashboard 页面:
import * as React from "react";
import { Navigate } from "react-router-dom";
class LoginForm extends React.Component {
state = { user: null, error: null };
async handleSubmit(event) {
event.preventDefault();
try {
let user = await login(event.target);
this.setState({ user });
} catch (error) {
this.setState({ error });
}
}
render() {
let { user, error } = this.state;
return (
<div>
{error && <p>{error.message}</p>}
{user && (
<Navigate to="/dashboard" replace={true} />
)}
<form
onSubmit={(event) => this.handleSubmit(event)}
>
<input type="text" name="username" />
<input type="password" name="password" />
</form>
</div>
);
}
}
<Outlet>
类型定义:
interface OutletProps {
context?: unknown;
}
declare function Outlet(
props: OutletProps
): React.ReactElement | null;
<Outlet>
可用于父路由中,用来渲染子路由组件. 这需要开发者合理安排嵌套 UI 的布局. 当直接访问父路由时,会自动渲染父路由中配置了 index 属性的子路由来替代 Outlet
, 如果没有 index 路由,该位置不渲染。
下面的例子中,访问 /
会渲染 Dashboard 组件, Outlet留白; 访问 /tasks
则会渲染 Dashboard,Outlet位置会渲染 DashboardTasks:
function Dashboard() {
return (
<div>
<h1>Dashboard</h1>
<Outlet />
</div>
);
}
function App() {
return (
<Routes>
<Route path="/" element={<Dashboard />}>
<Route
path="messages"
element={<DashboardMessages />}
/>
<Route path="tasks" element={<DashboardTasks />} />
</Route>
</Routes>
);
}
当然了,父子组件仍然可以传参,使用 context 和 useOutletContext 组合拳即可,详情可参考本专栏的 hook 专题。
<Routes> 与 <Route>
类型声明:
declare function Routes(
props: RoutesProps
): React.ReactElement | null;
interface RoutesProps {
children?: React.ReactNode;
location?: Partial<Location> | string;
}
declare function Route(
props: RouteProps
): React.ReactElement | null;
interface RouteProps {
caseSensitive?: boolean;
children?: React.ReactNode;
element?: React.ReactNode | null;
index?: boolean;
path?: string;
}
<Routes>
和 <Route>
是 React Router 中主要的配置类型。可以把 <Route>
看做是一个 if
判断:如果 path
匹配了当前 URL, 则会渲染他的 element
!使用 <Route caseSensitive>
可以启用路由大小写匹配。
当 location 变化时, <Routes>
会遍历下属 children
的所有 <Route>
以试图寻找最佳匹配的路由. <Route>
所在路径跟嵌套 UI 的路径位置是一致的,所见即所得的渲染方式。
例子:
<Routes>
<Route path="/" element={<Dashboard />}>
<Route
path="messages"
element={<DashboardMessages />}
/>
<Route path="tasks" element={<DashboardTasks />} />
</Route>
<Route path="about" element={<AboutPage />} />
</Routes>
Note:
Routes 的 Javascript替代品见
useRoutes
.
<Route element>
会默认往下渲染,并且拼接路径,所以不是每一个 Route 都需要配置一个 element 属性。
比如说下面的例子, 路径 /users/:id
依然可以匹配到 UserProfile 元素,而不用担心路径被截断:
<Route path="users">
<Route path=":id" element={<UserProfile />} />
</Route>
『完』