[email protected] 压缩后 20.8k
[email protected] 压缩后 10.8k
path
:与当前页面对用的URL匹配
element
:新增,用于决定路由匹配时,渲染哪个组件,代替,v5的compongnt
和render
Routes
>代替了<Switch
>Outlet
><Outlet
>让嵌套路由更简单useNavigate
代替useHistory
NavLink
/>的activeClassName
和activeStyle
useRoutes
代替了react-router-config
<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属性,他和父路由共享同一个路径。
(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}){
//路由提供的钩子useNavigate()
const navigate =useNavigate ()
useEffect(() => {
navigate(to, {replace:true})
})
return null
}
(3)404如何实现
<Route path="/" element={ <Redirect to="/film"/>}/>
<Route path="*" element={ <Notfound />}/>
<Routes>
<Route path="/film" element={<Film />}>
{/* 嵌套路由重定向 film中使用 容器 */}
{/* 匹配到父路径就显示一个NowPlaying子路径 插入到Outlet容器中 */}
{/* 方案1 */}
{/* }> */}
{/* 方案2 可以使用path='' 或者 index*/}
<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></Outlet>
</div>
<ul>
<li> <NavLink to="nowplaying" className={({ isActive }) => isActive ? "kerwinactive" :""} >正在热映</NavLink></li>
<li><NavLink to="comingsoon" className={({ isActive }) => isActive ? "kerwinactive" :""}>即将上映</NavLink></li>
</ul>
//url传参
const navigate = useNavigate()
navigate( /detail?id=${id}^ )
//获取url参数
import { useSearchParams } from' react-router-dom'
const[ searchparams, setSearchparams] = useSearchParams()
// 获取参数
searchparams.get('id')
//判断参数是否存在
searchParams.has('id')
//同时页面内也可以用set方法来改变路由
setSearchParams ({"id":2})
<Route path="/detail/:id" element={<Detail />}></Route>
import { useNavigate } from "react-router-dom";
const navigate = useNavigate();
const handleChangePage = (id) => {
//跳转页面 普通方式
//query 传参 /detail?id=1000
//路由传参 /detail/1000
// navigate(`/detail?id=${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]);
//修改id
return (
<div
onClick={() => {
navigate(`/detail/1000`);
}}
>
猜你喜欢
</div>
);
}
路由拦截:路由跳转之前,先进行一次验证,验证通过则跳转 ,长用户受保护的组件,登陆后才可访问
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>;
}
/*
* @Version: 2.0
* @Autor: CQJ
* @Date: 2022-03-28 10:02:36
* @LastEditTime: 2022-03-29 15:55:35
* @LastEditors: CQJ
* @Description:使用BrowserRouter需要后端配置,如果路径请求是后端处理不了的,就渲染index.html给前端处理
*/
import "./App.css";
//两种模式 HashRouter BrowserRouter
import { BrowserRouter as Router } from "react-router-dom";
import MyRouter from "./Router";
import Tarbar from "./components/Tarbar";
function App() {
//项目外层套上Router
return (
<Router>
{/* 匹配到/film路径后,加载Film组件 */}
<MyRouter />
<Tarbar />
</Router>
);
}
export default App;
函数式组件使用useNavigate()钩子
import React from "react";
import { useNavigate } from "react-router-dom";
export default function FilmItem(props) {
//props.history.push() 此时没有路由属性
const navigate = useNavigate();
const handleChangePage = () => {
//跳转页面
//query 传参 /detail?id=1000
//路由传参 /detail/1000
// navigate(`/detail?id=${id}`);
// 动态路由
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}`);
//this.props.history.push 跳转页面
//this.props.history.params 获取参数
//this.props.history.location 获取当前路由
}
}
export default WithRouter(FilmItem);
const LazyLoad = (path) => {
const Comp = React. lazy(() => import( `../views/${path}` ))
return (
<React. Suspense fallback={ <>加载中...</>}>
<Comp />
</React. Suspense>
)
/*
* @Version: 2.0
* @Autor: CQJ
* @Date: 2022-03-28 10:16:28
* @LastEditTime: 2022-03-29 17:55:18
* @LastEditors: CQJ
* @Description:
*/
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>
);
};