react路由

v6

来源

react-router vue-router

  • SPA 出现后, 前端才开始自己接管路由
    • 现在,客户端接管了路由。
  • router 是啥
    • 路由的变化,是不是就是意味着界面(部分内容)的变化
    • 界面的变化,意味着数据的变化,组件的变化。
    • keywords: context, components, path(/user/edit)
  • 路由的核心
    • 根据/监听 path/url 的变化,根据 path 和 components 之间的对应关系,触发组件进行unmount 和 mount,同时使用 context 注入上下文
      • navigation
      • path

react-router

提供一些核心的 API, 如:Router, Route 这些,但是不提供和 DOM 相关的

react-router-dom

提供 BrowserRouter, HashRouter, Link 这些 API,可以通过 DOM 操作触发事件,控制路由

history

模拟浏览器的 history 的一个库, V6 的版本这个库已经内置的,并且导出成 navigation

react-router-dom v6

  • 已经没有 component 了,用 element 代替
Routes

一组路由,代替原来的 Switch

Route

基础路由

Link
Outlet

类似于 Vue 中的 router-view

useRoutes、useParams、useNavigate(代替以前的 useHistory)、useLocation
import { BrowserRouter, Outlet, Route, Routes, useLocation, useNavigate, useParams, useRoutes } from 'react-router-dom';
import { lazy,Suspense  } from 'react';
import { Link } from 'react-router-dom';//写法1
function App_old() {return <BrowserRouter><Routes><Route path="/list" element={<div>新闻列表--pages</div>} /><Route path="/about" element={<div>关于我们--pages</div>} /><Route path="/hot" element={<div>热点新闻--pages</div>} /></Routes></BrowserRouter>
}
//写法2
const NavMenu = ({ to, children }) => (<div className=' border-x border-gray-500 border-solid px-10 py-1 whitespace-nowrap'><Link to={to} >{children}</Link></div>
)const Menu = () => (<div><header className=' w-full h-14 flex flex-row justify-start items-center bg-blue-200 '><NavMenu to="./" >首页</NavMenu><NavMenu to="./list" >新闻列表</NavMenu><NavMenu to="./about" >关于我们</NavMenu><NavMenu to="./hot" >热点新闻</NavMenu></header><Outlet /></div>
)
const List = () => {const nav = useNavigate();return <div>this is the news Page<button onClick={() => nav('/post/1')} >去新闻1</button></div>
}
const Post = () => {const { id } = useParams();const location = useLocation();console.log(location)return <div>{id}: 新闻信息</div> 
}const App_old_Outlet = () => {return <BrowserRouter><Routes><Route path='/' element={<Menu />}><Route path='/list' element={<List />} /><Route path='/about' element={<div>关于我们--pages</div>} /><Route path="/hot" element={<div>热点新闻--pages</div>} /></Route></Routes></BrowserRouter>
}//写法3let routes = [{path: '/', element: <Menu />,children: [{ path: '/list', element: <List />},{ path: '/post/:id', element: <Post />},{ path: '/about', element: <div>关于我们--pages--json</div>},{ path: '/hot', element: <div><Suspense fallback={<div>loading</div>}><DynamicNews /></Suspense></div>},]}
]const Routing = () => useRoutes(routes)const App = () => {return <BrowserRouter><Routing /></BrowserRouter>
}
手写router实现
import { createBrowserHistory, createHashHistory } from "history";
import { useLayoutEffect, useState } from "react";
import { useMemo } from "react";
import { useRef } from "react";
import { useContext } from "react";
import React,  { createContext } from "react";// 创建上下文
const NavigationContext = createContext({});
const LocationContext = createContext({});export function HashRouter({ children }) {let historyRef = useRef();if(historyRef.current == null) {historyRef.current = createHashHistory();};let history = historyRef.current;let [ state, setState ] = useState({action: history.action,location: history.location})use//  我们需要监听 history 的变化, 用useLayoutEffect// 当 history 变化的时候,(浏览器输入、获取a标签跳转,api跳转)// 派发更新,渲染整个 router 树useLayoutEffect(() => history.listen(setState), [history]);return <Router children={children}location={state.location}navigator={history}navigationType={state.action}/>
}export function BrowserRouter({ children }) {let historyRef = useRef();if(historyRef.current == null) {historyRef.current = createBrowserHistory();};let history = historyRef.current;let [ state, setState ] = useState({action: history.action,location: history.location})//  我们需要监听 history 的变化, 用useLayoutEffect// 当 history 变化的时候,(浏览器输入、获取a标签跳转,api跳转)// 派发更新,渲染整个 router 树useLayoutEffect(() => history.listen(setState), [history]);return <Router children={children}location={state.location}navigator={history}navigationType={state.action}/>
}// Provider 
function Router({ children, location: locationProp, navigator}) {const navigationContext = useMemo(() => ({ navigator }), [navigator]);const locationContext = useMemo(() => ({ location: locationProp }), [locationProp])return <NavigationContext.Provider value={navigationContext}><LocationContext.Providervalue={locationContext}children={children}></LocationContext.Provider></NavigationContext.Provider>
}function useLocation() {return useContext(LocationContext).location;
}function useNavigate() {return useContext(NavigationContext).navigator;
}// const Routing = () => useRoutes(routes)
// Routing 就是 我跟你 routes 参数的内容,
// 结合当前浏览器上的 url, 返回具体是哪个 element
function useRoutes(routes) {let location = useLocation(); // 当前路径let currentPath = location.pathname || '/';console.log(currentPath)for(let i = 0; i < routes.length; i++) {let { path, element } = routes[i];let match = currentPath.match(new RegExp(`^${path}`));if(match) {return element;}}return null;
}
// Routes 这个东西,
// 我就是要把所有的 Route 组件,创建成一棵树
export const Routes = ({ children }) => useRoutes(createRoutesFromChildren(children));export const Route = () => {}// 我就是要把 <Route /> 的嵌套,转成一棵树。
export const createRoutesFromChildren = (children) => {let routes = [];React.Children.forEach(children, (node) => {let route = {element: node.props.element,path: node.props.path,};if(node.props.children) {route.children = createRoutesFromChildren(node.props.children)}routes.push(route);});console.log(routes)return routes;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/847180.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

语言模型解构——Tokenizer

1. 认识Tokenizer 1.1 为什么要有tokenizer&#xff1f; 计算机是无法理解人类语言的&#xff0c;它只会进行0和1的二进制计算。但是呢&#xff0c;大语言模型就是通过二进制计算&#xff0c;让你感觉计算机理解了人类语言。 举个例子&#xff1a;单1&#xff0c;双2&#x…

【传知代码】探索视觉与语言模型的可扩展性(论文复现)

前言&#xff1a;在数字化时代的浪潮中&#xff0c;我们见证了人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;其中视觉与语言模型作为两大核心领域&#xff0c;正以前所未有的速度改变着我们的生活和工作方式。从图像识别到自然语言处理&#xff0c;从虚拟现实…

无人机推流/RTMP视频推拉流EasyDSS无法卸载软件是什么原因?

视频推拉流/直播点播EasyDSS平台支持音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务&#xff0c;在应用场景中可实现视频直播、点播、转码、管理、录像、检索、时移回看等。此外&#xff0c;平台还支持用户自行上传视频文件&#xff0c;也可将上传的点播…

力扣2841.几乎唯一子数组的最大和

力扣2841.几乎唯一子数组的最大和 哈希表存数字出现次数 没了就erase class Solution {public:long long maxSum(vector<int>& nums, int m, int k) {long long ans 0, sum 0;unordered_map<int,int> cnt;for(int i0;i<k-1;i){sum nums[i];cnt[nums[i…

大话设计模式解读01-简单工厂模式

本系列的文章&#xff0c;来介绍编程中的设计模式&#xff0c;介绍的内容主要为《大话设计模式》的读书笔记&#xff0c;并改用C语言来实现&#xff08;书中使用的是.NET中的C#&#xff09;,本篇来学习第一章&#xff0c;介绍的设计模式是——简单工厂模式。 1 面向对象编程 …

Mixly 开启WIFI AP UDP收发数据

一、开发环境 软件&#xff1a;Mixly 2.0在线版 硬件&#xff1a;ESP32-C3&#xff08;立创实战派&#xff09; 固件&#xff1a;ESP32C3 Generic(UART) 测试工工具&#xff1a;NetAssist V5.0.1 二、实现功能 ESP32开启WIFI AP&#xff0c;打印接入点IP地址&#xff0c;允许…

基于RNN和Transformer的词级语言建模 代码分析 数据集的处理 Dictionary 和 Corpus

基于RNN和Transformer的词级语言建模 代码分析 数据集的处理 Dictionary 和 Corpus flyfish Word-level Language Modeling using RNN and Transformer word_language_model PyTorch 提供的 word_language_model 示例展示了如何使用循环神经网络RNN(GRU或LSTM)和 Transform…

模拟堆-java

模拟堆也是对堆的一次深入理解和一些其它操作&#xff0c;可以了解一下。 文章目录 前言 一、模拟堆 二、算法思路 1.结点上移 2.结点下移 3.插入一个数 4.输出当前集合的最小值 5.删除当前集合的最小值&#xff08;数据保证此时的最小值唯一&#xff09; 6.删除第k个插入的数 …

Springboot健身房管理系统-计算机毕业设计源码44394

摘 要 大数据时代下&#xff0c;数据呈爆炸式地增长。为了迎合信息化时代的潮流和信息化安全的要求&#xff0c;利用互联网服务于其他行业&#xff0c;促进生产&#xff0c;已经是成为一种势不可挡的趋势。在健身房管理的要求下&#xff0c;开发一款整体式结构的健身房管理系统…

代理 模式

一、什么是代理模式 代理模式指代理控制对其他对象的访问&#xff0c;也就是代理对象控制对原对象的引⽤。在某些情况下&#xff0c;⼀个对象不适合或者不能直接被引⽤访问&#xff0c;⽽代理对象可以在客⼾端和⽬标对象之间起到中介的作⽤。 二、为什么使用代理模式 模式作…

HW面试常见知识点2——研判分析(蓝队中级版)

&#x1f340;文章简介&#xff1a;又到了一年一度的HW时刻&#xff0c;本文写给新手想快速进阶HW蓝中的网安爱好者们&#xff0c; 通读熟练掌握本文面试定个蓝中还是没问题的&#xff01;大家也要灵活随机应变&#xff0c;不要太刻板的回答&#xff09; &#x1f341;个人主页…

揭秘下载数据背后的秘密,Xinstall助你掌握市场脉搏

在当下这个移动互联网时代&#xff0c;应用推广已成为各大企业竞争的重要战场。然而&#xff0c;如何有效地获取并分析应用下载数据&#xff0c;却成为了许多推广者面临的难题。今天&#xff0c;我们将为大家介绍一款强大的应用推广助手——Xinstall&#xff0c;它能够帮助你轻…

JavaScript表单验证

表单验证是指在提交表单数据之前对用户输入的数据进行检测和验证&#xff0c;以确保数据的完整性和准确性。JavaScript是一种常用的前端编程语言&#xff0c;可以使用JavaScript来实现表单验证。 下面是一些常见的表单验证的例子&#xff0c;以及相应的JavaScript代码解释。 …

【chatgpt】学术翻译和英文润色prompt

学术翻译&#xff1a; I want you to act as a scientific English-Chinese translator, I will provide you with some paragraphs in one language and your task is to accurately and academically translate the paragraphs only into the other language. I want you pro…

隐藏 IP 地址的重要性是什么?

在当今的数字时代&#xff0c;保护我们的在线身份至关重要。从保护个人信息到保护隐私&#xff0c;互联网用户越来越多地寻求增强在线安全性的方法。保持匿名和保护敏感数据的一个关键方面是隐藏您的 IP 地址。在这篇博文中&#xff0c;我们将深入探讨隐藏 IP 地址的重要性&…

人脸识别技术与人证合一智能闸机的剖析

人脸识别技术&#xff0c;作为一种先进的生物认证手段&#xff0c;依据个体面部独有的特征信息来进行身份验证。这项技术通过捕获图像或视频中的面部数据&#xff0c;执行一系列精密步骤&#xff0c;包括图像获取、面部定位、预处理、特征提取与比对&#xff0c;以确认个人身份…

【JMeter接口自动化】第2讲 Jmeter目录结构

JMeter的目录结构如下&#xff1a; bin目录&#xff1a;可执行文件目录&#xff0c;启动jmeter时&#xff0c;就是启动bin目录下的ApacheJmeter.jar&#xff0c;jmeter.bat&#xff0c;jmeter.sh ApacheJmeter.jar:启动文件 jmeter.bat&#xff1a;Windows 的启动命令。 jmeter…

前端框架前置知识之Node.js:fs模块、path模块、http模块、端口号介绍

什么是模块&#xff1f; 类似插件&#xff0c;封装了方法 / 属性 fs 模块- 读写文件 代码示例 // 1. 加载 fs 模块对象 const fs require(fs) // 2. 写入文件内容 fs.writeFile(./test.txt, hello, Node.js, (err) > {if (err) console.log(err) //若 err不为空&#xf…

printf 一次性写

PWN里printf漏洞感觉很小&#xff0c;可发现居然理解的不全。 一般情况下&#xff0c;当buf不在栈内时&#xff0c;就不能直接写指针。这时候需要用到rbp链或者argv链。一般操作是第一次改指针&#xff0c;第二次改数值。 DAS昨天这里只给了一次机会然后就exit了。今天ckyen给…

韩顺平0基础学java——第15天

p303-326 重写override 和重载做个对比 注&#xff1a;但子类可以扩大范围&#xff0c;比如父类是protected&#xff0c;子类可以是public 多态 方法或对象具有多种形态&#xff0c;是面向对象的第三大特征&#xff0c;多态是建立在封装和继承基础之上的。 多态的具体体现…