1 引言
React Router v6 alpha 版本发布了,本周通过 A Sneak Peek at React Router v6 这篇文章分析一下带来的改变。
2 概述
更名为
一个不痛不痒的改动,使 API 命名更加规范。
// v5
import { BrowserRouter, Switch, Route } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Switch>
import { BrowserRouter, Switch, Route } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/profile">
<Profile />
</Route>
</Switch>
</BrowserRouter>
);
}
<Home />
</Route>
<Route path="/profile">
<Profile />
</Route>
</Switch>
</BrowserRouter>
);
}
在 React Router v6 版本里,直接使用 Routes 替代 Switch:
// v6
import { BrowserRouter, Routes, Route } from "react-router-dom";
import { BrowserRouter, Routes, Route } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="profile/*" element={<Profile />} />
</Routes>
</BrowserRouter>
);
}
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="profile/*" element={<Profile />} />
</Routes>
</BrowserRouter>
);
}
升级
在 v5 版本里,想要给组件传参数是不太直观的,需要利用 RenderProps 的方式透传 routeProps:
import Profile from './Profile';
// v5
<Route path=":userId" component={Profile} />
<Route
path=":userId"
render={routeProps => (
<Profile {...routeProps} animate={true} />
)}
/>
// v6
<Route path=":userId" element={<Profile />} />
<Route path=":userId" element={<Profile animate={true} />} />
而在 v6 版本中,render 与 component 方案合并成了 element 方案,可以轻松传递 props 且不需要透传 roteProps 参数。
更方便的嵌套路由
在 v5 版本中,嵌套路由需要通过 useRouteMatch 拿到 match,并通过 match.path 的拼接实现子路由:
// v5
import {
BrowserRouter,
Switch,
Route,
Link,
useRouteMatch
} from "react-router-dom";
function App() {
return (
import {
BrowserRouter,
Switch,
Route,
Link,
useRouteMatch
} from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/profile" component={Profile} />
</Switch>
</BrowserRouter>
);
}
function Profile() {
let match = useRouteMatch();
return (
<div>
<nav>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/profile" component={Profile} />
</Switch>
</BrowserRouter>
);
}
function Profile() {
let match = useRouteMatch();
return (
<div>
<nav>
<Link to={`${match.url}/me`}>My Profile</Link>
</nav>
<Switch>
<Route path={`${match.path}/me`}>
<MyProfile />
</Route>
<Route path={`${match.path}/:id`}>
<OthersProfile />
</Route>
</Switch>
</div>
);
}
</nav>
<Switch>
<Route path={`${match.path}/me`}>
<MyProfile />
</Route>
<Route path={`${match.path}/:id`}>
<OthersProfile />
</Route>
</Switch>
</div>
);
}
在 v6 版本中省去了 useRouteMatch 这一步,支持直接用 path 表示相对路径:
// v6
import { BrowserRouter, Routes, Route, Link, Outlet } from "react-router-dom";
// Approach #1
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="profile/*" element={<Profile />} />
</Routes>
</BrowserRouter>
);
}
import { BrowserRouter, Routes, Route, Link, Outlet } from "react-router-dom";
// Approach #1
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="profile/*" element={<Profile />} />
</Routes>
</BrowserRouter>
);
}
function Profile() {
return (
<div>
<nav>
<Link to="me">My Profile</Link>
</nav>
<Routes>
<Route path="me" element={<MyProfile />} />
<Route path=":id" element={<OthersProfile />} />
</Routes>
</div>
);
}
/
return (
<div>
<nav>
<Link to="me">My Profile</Link>
</nav>
<Routes>
<Route path="me" element={<MyProfile />} />
<Route path=":id" element={<OthersProfile />} />
</Routes>
</div>
);
}
/
/ Approach #2
// You can also define all
// <Route> in a single place
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="profile" element={<Profile />}>
<Route path=":id" element={<MyProfile />} />
<Route path="me" element={<OthersProfile />} />
</Route>
</Routes>
</BrowserRouter>
);
// You can also define all
// <Route> in a single place
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="profile" element={<Profile />}>
<Route path=":id" element={<MyProfile />} />
<Route path="me" element={<OthersProfile />} />
</Route>
</Routes>
</BrowserRouter>
);
}
function Profile() {
return (
<div>
<nav>
<Link to="me">My Profile</Link>
</nav>
<Outlet />
</div>
);
}
function Profile() {
return (
<div>
<nav>
<Link to="me">My Profile</Link>
</nav>
<Outlet />
</div>
);
}
注意 Outlet 是渲染子路由的 Element。
useNavigate 替代 useHistory
在 v5 版本中,主动跳转路由可以通过 useHistory 进行 history.push 等操作:
// v5
import { useHistory } from "react-router-dom";
function MyButton() {
let history = useHistory();
function handleClick() {
history.push("/home");react router路由传参
}
return <button onClick={handleClick}>Submit</button>;
}
import { useHistory } from "react-router-dom";
function MyButton() {
let history = useHistory();
function handleClick() {
history.push("/home");react router路由传参
}
return <button onClick={handleClick}>Submit</button>;
}
而在 v6 版本中,可以通过 useNavigate 直接实现这个常用操作:
// v6
import { useNavigate } from "react-router-dom";
import { useNavigate } from "react-router-dom";
function MyButton() {
let navigate = useNavigate();
function handleClick() {
navigate("/home");
}
return <button onClick={handleClick}>Submit</button>;
}
react-router 内部对 history 进行了封装,如果需要 place,可以通过 { replace: true } 参数指定:
// v5
history.push("/home");
place("/home");
/
history.push("/home");
place("/home");
/
/ v6
navigate("/home");
navigate("/home", { replace: true });
navigate("/home");
navigate("/home", { replace: true });
更小的体积 8kb
由于代码几乎重构,v6 版本的代码压缩后体积从 20kb 缩小到 8kb。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论