对比v5
1.包大小对比
react-router@5.1.2 压缩后 20.8k react-router@6.2.1 压缩后 10.8k
2.特性变更
path :与当前页面对用的URL匹配 element :新增,用于决定路由匹配时,渲染哪个组件,代替,v5的compongnt 和render
3.<Routes >代替了<Switch >
4.<Outlet ><Outlet >让嵌套路由更简单
5.useNavigate 代替useHistory
6.移除了<NavLink />的activeClassName 和activeStyle
7.钩子useRoutes 代替了react-router-config
用法详解
1.一级路由与多级路由
<Routes>
{}
<Route index element={<Film/>}/>
<Route path="/film" element={<Film/>}/>
<Route path="/cinemal" element={ <Cinema/>}/>
<Route path="/center" element={ <Center/>}/>
</Routes>
index用于嵌套路由,仅匹配父路径时,设置渲染的组件。 解决当嵌套路由有多个子路由但本身无法确认默认渲染哪个子路由的时候,可以增加index属性来指定默认路由。index路由和其他路由不同的地方是它没有path属性,他和父路由共享同一个路径。
2.路由重定向
(1)官方推荐方案1:使用Navagate组件代替
<Routes>
{}
<Route path="/film" element={ <Film/>}/>
<Route path="/cinema" element={ <Cinema/>}/>
<Route path="/center" element={ <Center/>}/>
<Route path="*" e1ement={ <Navigate to=" /film"/>}/>
</Routes>
(2)官方推荐方案2:自定义Redirect组件
<Route path="*" element={ <Redirect to="/film"/>}/>
function Redirect({to}){
const navigate =useNavigate ()
useEffect(() => {
navigate(to, {replace:true})
})
return null
}
(3)404如何实现
<Route path="/" element={ <Redirect to="/film"/>}/>
<Route path="*" element={ <Notfound />}/>
3.嵌套路由
<Routes>
<Route path="/film" element={<Film />}>
{}
{}
{}
{}
{}
<Route index element={<Redirect to="/film/nowplaying" />}></Route>
<Route path="nowplaying" element={<NowPlaying />}></Route>
<Route path="comingsoon" element={<ComingSoon />}></Route>
</Route>
</Routes>
film页面中
<div>
<div style={{ height: "200px", backgroundColor: "yellow" }}>大轮播</div>
<ul>
<li>正在热映</li>
<li>即将上映</li>
</ul>
{}
<Outlet></Outlet>
</div>
4.声明式和编程时导航
<ul>
<li> <NavLink to="nowplaying" className={({ isActive }) => isActive ? "kerwinactive" :""} >正在热映</NavLink></li>
<li><NavLink to="comingsoon" className={({ isActive }) => isActive ? "kerwinactive" :""}>即将上映</NavLink></li>
</ul>
const navigate = useNavigate()
navigate( /detail?id=${id}^ )
import { useSearchParams } from' react-router-dom'
const[ searchparams, setSearchparams] = useSearchParams()
searchparams.get('id')
searchParams.has('id')
setSearchParams ({"id":2})
5.动态路由
<Route path="/detail/:id" element={<Detail />}></Route>
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
const handleChangePage = (id) => {
navigate(`/detail/${id}`);
};
import React, { useEffect } from "react";
import { useParams, useNavigate } from "react-router-dom";
export default function Detail() {
const params = useParams();
console.log(params, "params");
const navigate = useNavigate();
useEffect(() => {
console.log("重新请求数据");
return () => {};
}, [params.id]);
return (
<div
onClick={() => {
navigate(`/detail/1000`);
}}
>
猜你喜欢
</div>
);
}
6.路由拦截
路由拦截:路由跳转之前,先进行一次验证,验证通过则跳转 ,长用户受保护的组件,登陆后才可访问
1.方法判断
<Route
path="/center"
element={isAuth() ? <Center /> : <Redirect to="/login" />}
></Route>
function isAuth() {
return localStorage.getItem("token");
}
2.组件判断(使用一个验证组件来决定是否渲染)
<Route
path="/center"
element={
<AuthComponent>
<Center></Center>
</AuthComponent>
}
></Route>
function AuthComponent({ children }) {
console.log(children, "children");
const isLogin = localStorage.getItem("token");
return isLogin ? children : <Redirect to="/login"></Redirect>;
}
7.路由模式
import "./App.css";
import { BrowserRouter as Router } from "react-router-dom";
import MyRouter from "./Router";
import Tarbar from "./components/Tarbar";
function App() {
return (
<Router>
{}
<MyRouter />
<Tarbar />
</Router>
);
}
export default App;
8.withRouter(v6中使用useNavigate()) 适用于类组件
函数式组件使用useNavigate()钩子
import React from "react";
import { useNavigate } from "react-router-dom";
export default function FilmItem(props) {
const navigate = useNavigate();
const handleChangePage = () => {
navigate(`/detail/${props.filmId}`);
};
return (
<div>
<li onClick={() => handleChangePage()}>{props.name}</li>
</div>
);
}
this.props.history这个路由属性不是每个组件都有的,必须被包裹的才有,组件的孩子,孩子的孩子可以使用withRouter
非要使用类组件 的话也可以封装一个withRouter 相当于withRouter的源码
import { useLocation, useNavigate, useParams } from "react-router-dom";
function withRouter(Component) {
function ComponentwithRouterprop(props) {
let location = useLocation();
let push = useNavigate();
let params = useParams();
return <Component {...props} history={{ location, push, params }} />;
}
return ComponentWithRouterprop;
}
页面使用withRouter
import React, { Component } from "react";
import WithRouter from "../../components/WithRouter";
class FilmItem extends Component {
render() {
console.log(this.props.history, "history");
console.log(this.props.history.push, "push");
console.log(this.props.history.params, "params");
console.log(this.props.history.location, "params");
return (
<li onClick={() => this.handleClick(this.props.filmId)}>
{this.props.name}
</li>
);
}
handleClick(id) {
console.log(id);
this.props.history.push(`/detail/${id}`);
}
}
export default WithRouter(FilmItem);
9.路由懒加载
const LazyLoad = (path) => {
const Comp = React. lazy(() => import( `../views/${path}` ))
return (
<React. Suspense fallback={ <>加载中...</>}>
<Comp />
</React. Suspense>
)
import React from "react";
import { useRoutes } from "react-router-dom";
import Redirect from "../components/Redirect";
export default function MyRouter() {
const element = useRoutes([
{
path: "/film",
element: LazyLoad("Film"),
children: [
{ path: "", element: <Redirect to="/film/nowplaying" /> },
{ path: "nowplaying", element: LazyLoad("films/NowPlaying") },
{ path: "comingsoon", element: LazyLoad("films/ComingSoon") },
],
},
{
path: "/cinema",
element: LazyLoad("Cinema"),
},
{
path: "/cinema/search",
element: LazyLoad("Search"),
},
{
path: "/login",
element: LazyLoad("Login"),
},
{
path: "/center",
element: <AuthComponent>{LazyLoad("Center")}</AuthComponent>,
},
{
path: "/detail/:id",
element: LazyLoad("Detail"),
},
{
path: "/",
element: <Redirect to="/film" />,
},
{
path: "*",
element: LazyLoad("NotFound"),
},
]);
return element;
}
function isAuth() {
return localStorage.getItem("token");
}
function AuthComponent({ children }) {
console.log(children, "children");
const isLogin = localStorage.getItem("token");
return isLogin ? children : <Redirect to="/login"></Redirect>;
}
const LazyLoad = (path) => {
const Comp = React.lazy(() => import(`../views/${path}`));
return (
<React.Suspense fallback={<>...加载中</>}>
<Comp />
</React.Suspense>
);
};
|