React-Router v5-v6区别

对比v5

1.包大小对比

react-router@5.1.2 压缩后 20.8k
react-router@6.2.1 压缩后 10.8k

2.特性变更

path:与当前页面对用的URL匹配
element:新增,用于决定路由匹配时,渲染哪个组件,代替,v5的compongntrender

3.<Routes>代替了<Switch>
4.<Outlet><Outlet>让嵌套路由更简单
5.useNavigate代替useHistory
6.移除了<NavLink/>的activeClassNameactiveStyle
7.钩子useRoutes代替了react-router-config
8.https://reactrouter.com/docs/en/v6/upgradingv5

用法详解

1.一级路由与多级路由
<Routes>
{/*<Route path="/" element={ <Film/>}/>*/}
	<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 index element={<Film/>}/> */}
	<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 />}/>
3.嵌套路由
<Routes>
	<Route path="/film" element={<Film />}>
        {/* 嵌套路由重定向 film中使用<Outlet></Outlet>容器 */}
        {/* 匹配到父路径就显示一个NowPlaying子路径 插入到Outlet容器中 */}
        {/* 方案1 */}
        {/* <Route index element={<NowPlaying />}></Route> */}
        {/* 方案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>
4.声明式和编程时导航
<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})
5.动态路由
<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>
  );
}

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.路由模式
/*
 * @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;

8.withRouter(v6中使用useNavigate()) 适用于类组件

函数式组件使用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);

9.路由懒加载
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>
  );
};

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值