IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> React-Router v5-v6区别 -> 正文阅读

[JavaScript知识库]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>
  );
};

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:14:48  更:2022-03-30 18:15:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:06:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码