react 路由的基本原理及实现

1. react 路由原理

不同路径渲染不同的组件
有两种实现方式
● HasRouter 利用hash实现路由切换
● BrowserRouter 实现h5 API实现路由切换

1. 1 HasRouter

利用hash 实现路由切换
在这里插入图片描述

1.2 BrowserRouter

利用h5 Api实现路由的切换

1.2.1 history
  • HTML5规范给我们提供了一个history接口
  • HTML5 HIstory API包含两个方法:history.pushState()和history.replaceState(),和一个事件
    window.onpopstate pushState
1.2.1.1 history.pushState(stateObject,title,url)

● 第一个参数用于存储该url对应的状态对象,该对象可在onpopstate事件中获取,也可在history对象中获取
● 第二个参数是标题,目前浏览器并未实现
● 第三个参数是设定的url
pushState函数向浏览器的历史堆栈中压入一个url为设定值的记录,并改变历史堆栈的当前指针至栈顶

1.2.1.2 replaceState

● 该接口与pushState参数相同,含义 也相同
● 唯一的区别在于replaceState是替换浏览器历史栈中的当前历史记录为设定的url
● 需要注意的是replaceState 不会改动浏览器历史堆栈的当前指针

1.2.1.3 onpopstate

● 该事件是window属性
● 该事件会在调用浏览器的前进,后退以及在执行history.forward,history.back 和history.go 的时候触发。因为这些操作有一个共性,即修改了历史堆栈的当前指针
● 在不改变document 的前提下,一旦触发当前指针改变则会触发onpopstate事件

2 实现基本路由

2.1 HashRouter 基本用法及实现

import React from 'react';
import { Router } from '../react-router';
import { createHashHistory } from '../history';
class HashRouter extends React.Component {constructor(props) {super(props);this.history = createHashHistory(props)}render() {return (<Router history={this.history}>{this.props.children}</Router>)}
}
export default HashRouter;

history 下的 createHashHistory.js

/*** 工厂方法,用来返回一个历史对象*/
function createHashHistory(props) {let stack = [];//模拟一个历史条目栈,这里放的都是每一次的locationlet index = -1;//模拟一个当前索引let action = 'POP';//动作let state;//当前状态let listeners = [];//监听函数的数组let currentMessage;let userConfirm = props.getUserConfirmation?props.getUserConfirmation():window.confirm;function go(n) {//go是在历史条目中跳前跳后,条目数不会发生改变action = 'POP';index += n;if(index <0){index=0;}else if(index >=stack.length){index=stack.length-1;}let nextLocation = stack[index];state=nextLocation.state;window.location.hash = nextLocation.pathname;//用新的路径名改变当前的hash值}function goForward() {go(1)}function goBack() {go(-1)}let listener = ()=>{let pathname = window.location.hash.slice(1);// /users#/api  /apiObject.assign(history,{action,location:{pathname,state}}); if(action === 'PUSH'){stack[++index]=history.location;//1 2 3 6 5 //stack.push(history.location);}listeners.forEach(listener=>listener(history.location));}window.addEventListener('hashchange',listener);//to={pathname:'',state:{}}function push(to,nextState){action = 'PUSH';let pathname;if(typeof to === 'object'){state = to.state;pathname = to.pathname;}else {pathname = to;state = nextState;}if(currentMessage){let message = currentMessage({pathname});let allow = userConfirm(message);if(!allow) return;}window.location.hash = pathname;}function listen(listener) {listeners.push(listener);return function () {//取消监听函数,如果调它的放会把此监听函数从数组中删除listeners = listeners.filter(l => l !== listener);}}function block(newMessage){currentMessage = newMessage;return ()=>{currentMessage=null;}}const history = {action,//对history执行的动作push,go,goBack,goForward,listen,location:{pathname:window.location.hash.slice(1),state:undefined},block}if(window.location.hash){action = 'PUSH';listener();}else{window.location.hash='/';}return history;
}export default createHashHistory;

2.2 BrowserRouter基本用法及实现

import React from 'react';
import { Router } from '../react-router';
import { createBrowserHistory } from '../history';
class BrowserRouter extends React.Component {constructor(props) {super(props);this.history = createBrowserHistory(props)}render() {return (<Router history={this.history}>{this.props.children}</Router>)}
}
export default BrowserRouter;

history 下的 createBrowserHistory.js

/*** 工厂方法,用来返回一个历史对象*/
function createBrowserHistory(props){let globalHistory = window.history;let listeners = [];let currentMessage;let userConfirm = props.getUserConfirmation?props.getUserConfirmation():window.confirm;function go(n){globalHistory.go(n);}function goForward(){globalHistory.goForward();}function goBack(){globalHistory.goBack();}function listen(listener){listeners.push(listener);return function(){//取消监听函数,如果调它的放会把此监听函数从数组中删除listeners = listeners.filter(l=>l!==listener);}}window.addEventListener('popstate',(event)=>{//push入栈 pop类似于出栈setState({action:'POP',location:{state:event.state,pathname:window.location.pathname}});});function setState(newState){Object.assign(history,newState);history.length = globalHistory.length;listeners.forEach(listener=>listener(history.location));}/*** push方法* @param {*} path 跳转的路径* @param {*} state 跳转的状态*/function push(to,nextState){//对标history pushStateconst action = 'PUSH';let pathname;let state;if(typeof to === 'object'){state = to.state;pathname = to.pathname;}else {pathname = to;state = nextState;}if(currentMessage){let message = currentMessage({pathname});let allow = userConfirm(message);if(!allow) return;}globalHistory.pushState(state,null,pathname);let location = {state,pathname};setState({action,location});}function block(newMessage){currentMessage = newMessage;return ()=>{currentMessage=null;}
}const history = {action:'POP',//对history执行的动作push,go,goBack,goForward,listen,location:{pathname:window.location.pathname,state:globalHistory.state},block}return history;
}export default createBrowserHistory;

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

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

相关文章

Android studio (一) 新建一个Android项目 编程语言为Java

一、下载Android studio 下载 Android Studio 和应用工具 - Android 开发者 | Android Developers 这里我下载的是2023年的 二、新建项目 选择如下模板。 填写项目名、项目保存位置、编程语言、最低支持Android API的版本、打包编译模式 三、报错Connection refused: no …

进程的通信以及信号的学习

一&#xff0c;进程的通信&#xff1a; 种类&#xff1a;1.管道 2.信号 3.消息队列 4.共享内存 5.信号灯 6.套接字 1.管道: 1.无名管道 无名管道只能用于具有亲缘关系的进程间通信 pipe int pipe(int pipefd[2]); 功能: 创建一个无名管道 …

机器学习——CBOW基于矩阵(手动实操)

基于矩阵的CBOW基础算法&#xff0c;其实是负采样的前提算法。 主要是根据 预测准确率为22%左右 说实话。。。我已经很满意了&#xff0c;至少这个东西是可以去预测的&#xff0c;至于预测为什么不正确&#xff0c;我目前猜测主要还是跟词频有关。 在结果中&#xff0c;an…

uniapp:启动图 .9png 制作教程

1、工具安装&#xff1a;自行下载Android Studio 2、制作.9png 注意上图3条黑线的位置&#xff0c;意思是&#xff1a;标注黑线的位置可以进行缩放。 对其大多数启动图来说&#xff0c;标注以上3条黑线即可。

ETH开源PPO算法学习

前言 项目地址&#xff1a;https://github.com/leggedrobotics/rsl_rl 项目简介&#xff1a;快速简单的强化学习算法实现&#xff0c;设计为完全在 GPU 上运行。这段代码是 NVIDIA Isaac GYM 提供的 rl-pytorch 的进化版。 下载源码&#xff0c;查看目录&#xff0c;整个项目…

创新之巅 健康之选 森歌集成灶智能水洗新揭秘

2024年2月27日&#xff0c;一场引领智能厨电风潮的盛会在杭州隆重召开。森歌集成灶以“勠力同心 共生共歌”为主题&#xff0c;成功举办了2024森歌智能厨电优秀经销商峰会。此次峰会上&#xff0c;森歌集成灶发布了令人瞩目的奥运冠军同款智能厨电新品——森歌鲸洗小灶Z60&…

前端架构: 脚手架之多package项目管理和架构

多package项目管理 1 &#xff09;多package项目管理概述 通常来说&#xff0c;当一个项目变大了以后&#xff0c;我们就要对这个项目进行拆分在前端当中&#xff0c;对于项目进行拆分的方式&#xff0c;通常把它称之为javascript包管理需要使用一个工具叫做 npm (Node Packag…

Java开发的核心模式 - MVC

文章目录 1、MVC设计模式2、Web开发本质3、服务器的性能瓶颈 1、MVC设计模式 MVC设计模式示意图 在整个Java学习之旅中&#xff0c;MVC&#xff08;Model-View-Controller&#xff09;设计模式无疑占据着极其重要的地位&#xff0c;堪称理解和掌握Java项目开发精髓的钥匙。如…

IP源防攻击IPSG(IP Source Guard)

IP源防攻击IPSG&#xff08;IP Source Guard&#xff09;是一种基于二层接口的源IP地址过滤技术&#xff0c;它能够防止恶意主机伪造合法主机的IP地址来仿冒合法主机&#xff0c;还能确保非授权主机不能通过自己指定IP地址的方式来访问网络或攻击网络。 2.1 IPSG基本原理 绑定…

关于delphi6提示[Fatal Error] File not found: ‘System.pas‘

关于delphi6提示[Fatal Error] File not found: System.pas 一、[Fatal Error] File not found: System.pas的原因 1、System.dcu的输出没有覆盖项目引用路径..\..\dcu下 2、注意事项&#xff1a;System.pas等源码不能赋值到..\..\dcu 3、下述控件的Tools-Environment Optio…

如何利用ChatGPT搞科研?论文检索、写作、基金润色、数据分析、科研绘图(全球地图、植被图、箱型图、雷达图、玫瑰图、气泡图、森林图等)

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

深入浅出JVM(十七)之并发垃圾收集器CMS

上篇文章介绍用户线程与GC线程并发执行时可能产生的问题以及使用三色标记法演示原始快照和增量更新两种解决方案 这篇文章将主要介绍并发垃圾收集器中的CMS&#xff0c;其中CMS使用增量更新来解决对象消失问题&#xff0c;如果不了解增量更新的同学可以查看上篇文章深入浅出JV…

【k8s 高级调度--污点和容忍】

1、调度概念 在 Kubernetes 中&#xff0c;调度&#xff08;scheduling&#xff09;指的是确保 Pod 匹配到合适的节点&#xff0c; 以便 kubelet 能够运行它们。 抢占&#xff08;Preemption&#xff09;指的是终止低优先级的 Pod 以便高优先级的 Pod 可以调度运行的过程。 驱逐…

为什么会对猫毛过敏?如何缓解?浮毛克星—宠物空气净化器推荐

猫咪过敏通常是因为它们身上的Fel d1蛋白质导致的&#xff0c;这些蛋白质附着在猫咪的皮屑上。猫咪舔毛的过程会带出这些蛋白质&#xff0c;一旦接触就可能引发过敏症状&#xff0c;比如打喷嚏等。因此&#xff0c;减少空气中的浮毛数量有助于减轻过敏现象。猫用空气净化器可以…

Tomcat架构分析

Tomcat的核心组件 Tomcat将请求器和处理器分离&#xff0c;使用多种请求器支持不同的网络协议&#xff0c;而处理器只有一个。从而网络协议和容器解耦。 Tomcat的容器 Host&#xff1a;Tomcat提供多个域名的服务&#xff0c;其将每个域名都视为一个虚拟的主机&#xff0c;在…

半导体行业案例:Jira与龙智插件助力某半导体企业实现精益项目管理

近日&#xff0c;龙智Atlassian技术团队收到了国内一家大型半导体企业的感谢信。龙智团队提供的半导体行业项目管理解决方案和服务受到了客户的好评&#xff1a; 在龙智团队的支持下&#xff0c;我们的业务取得了喜人的成果和进步。龙智公司的专业服务和产品&#xff0c;是我们…

skiplist(高阶数据结构)

目录 一、概念 二、实现 三、对比 一、概念 skiplist是由William Pugh发明的&#xff0c;最早出现于他在1990年发表的论文《Skip Lists: A Probabilistic Alternative to Balanced Trees》 skiplist本质上是一种查找结构&#xff0c;用于解决算法中的查找问题&#xff0c;…

AI:145-智能监控系统下的行人安全预警与法律合规分析

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带关键代码,详细讲解供大家学习,希望…

2024年阿里云2核4G配置服务器测评_ECS和轻量性能测评

阿里云2核4G服务器多少钱一年&#xff1f;2核4G服务器1个月费用多少&#xff1f;2核4G服务器30元3个月、85元一年&#xff0c;轻量应用服务器2核4G4M带宽165元一年&#xff0c;企业用户2核4G5M带宽199元一年。本文阿里云服务器网整理的2核4G参加活动的主机是ECS经济型e实例和u1…

Vue3制作一个可拖拽的小箭头

效果图 可以抓住小箭头进行左右拖拽&#xff0c;不会做git图&#xff0c;所以只有静态效果QAQ 代码 <template><div class"tip"draggable"true"dragstart"start" //拖拽开始时drag"dragging" //拖拽种dragend "…