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://xiahunao.cn/news/2814070.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

概率基础——正态分布

概率基础——正态分布 介绍 正态分布&#xff0c;又称高斯分布&#xff0c;是统计学中最重要的连续概率分布之一。它在自然界和人类活动中都有广泛的应用&#xff0c;被广泛用于描述各种自然现象和社会现象。正态分布的曲线呈钟形&#xff0c;以其特有的形态而著称&#xff0…

Ubuntu常用状态命令

目录 一、温度 1&#xff0c;查看CPU温度 2&#xff0c;查看硬盘温度 二、CPU状态 1&#xff0c;显示CPU的详细信息&#xff0c;包括型号、频率、缓存等 2&#xff0c;显示CPU架构、CPU核心数、线程数、频率等信息 三、登录状态 1&#xff0c;查看成功登录的用户 2&am…

day02_前后端环境搭建(前端工程搭建,登录功能说明,后端项目搭建)

文章目录 1. 软件开发介绍1.1 软件开发流程1.2 角色分工1.3 软件环境1.4 系统的分类 2. 尚品甄选项目介绍2.1 电商基本概念2.1.1 电商简介2.1.2 电商模式B2BB2CB2B2CC2BC2CO2O 2.2 业务功能介绍2.3 系统架构介绍2.4 前后端分离开发 3. 前端工程搭建3.1 Element-Admin简介3.2 El…

线性表——单链表的增删查改

本节复习链表的增删查改 首先&#xff0c; 链表不是连续的&#xff0c; 而是通过指针联系起来的。 如图&#xff1a; 这四个节点不是连续的内存空间&#xff0c; 但是彼此之间使用了一个指针来连接。 这就是链表。 现在我们来实现链表的增删查改。 目录 单链表的全部接口…

MySQL:开始深入其数据(一)DML

在上一章初识MySQL了解了如何定义数据库和数据表&#xff08;DDL&#xff09;&#xff0c;接下来我们开始开始深入其数据,对其数据进行访问&#xff08;DAL&#xff09;、查询DQL&#xff08;&#xff09;和操作(DML)等。 通过DML语句操作管理数据库数据 DML (数据操作语言) …

Qt篇——QTableWidget保存表格数据到Excel文件中,读Excel内容到QTableWidget

表格和excel例子如下图所示&#xff1a; 一、QTableWidget保存表格数据到Excel文件中 代码如下&#xff1a; &#xff08;pro文件中添加QT axcontainer&#xff09; #include <QAxObject>void MainWindow::saveTableToExcel() {QDateTime current_date_time QDateTi…

路由器端口映射如何配置?

在网络通信中&#xff0c;路由器是一个重要的设备&#xff0c;它负责将数据包从一个网络传输到另一个网络。路由器的端口映射配置是一种重要的设置&#xff0c;可以使外部网络中的计算机通过访问路由器上的特定端口与内部网络中的计算机进行通信。本文将介绍什么是路由器端口映…

4核8G服务器选阿里云还是腾讯云?价格性能对比

4核8G云服务器多少钱一年&#xff1f;阿里云ECS服务器u1价格955.58元一年&#xff0c;腾讯云轻量4核8G12M带宽价格是646元15个月&#xff0c;阿腾云atengyun.com整理4核8G云服务器价格表&#xff0c;包括一年费用和1个月收费明细&#xff1a; 云服务器4核8G配置收费价格 阿里…

全面升级!Apache HugeGraph 1.2.0版本发布

图数据库以独特的数据管理和分析能力&#xff0c;在企业数智化转型的过程中正在成为数据治理的核心&#xff0c;根据IDC调研显示&#xff0c;95%的企业认为图数据库是重要的数据管理工具&#xff0c;超过65%的厂商认为在业务上图数据库优于其他选择&#xff0c;尤其是在金融风控…

Centos6安装PyTorch要求的更高版本gcc

文章目录 CentOS自带版本安装gcc 4的版本1. 获取devtoolset-8的yum源2. 安装gcc3. 版本检查和切换版本 常见问题1. 找不到包audit*.rpm包2. 找不到libcgroup-0.40.rc1-27.el6_10.x86_64.rpm 的包4. cc: fatal error: Killed signal terminated program cc1plus5. pybind11/pybi…

工具使用-pwncat

pwncat是一个命令和控制框架&#xff0c;可以将基本的反向或绑定shell转化为一个功能齐全的利用平台。然后&#xff0c;它将尝试在远程主机上启动一个伪终端&#xff0c;并为您提供原始终端访问。 但pwncat不止于此。除了自动的获取全交互式终端外&#xff0c;pwncat还提供了一…

微服务-商城订单服务项目

文章目录 一、需求二、分析三、设计四、编码4.1 商品服务4.2 订单服务4.3 分布式事务4.4 订单超时 商品、购物车 商品服务&#xff1a; 1.全品类购物平台 SPU:Standard Product Unit 标准化产品单元。是商品信息聚合的最小单位。是一组可复用、易检索的标准化信息的集合&#x…

求两个向量之间的夹角

求两个向量之间的夹角 介绍Unity的API求向量夹角Vector3.AngleVector3.SignedAngle 自定义获取方法0-360度的夹角 总结 介绍 求两个向量之间的夹角方法有很多&#xff0c;比如说Unity中的Vector3.Angle&#xff0c;Vector3.SignedAngle等方法&#xff0c;具体在什么情况下使用…

4_透镜畸变

理论上讲&#xff0c;是可能定义一种透镜而不引入任何畸变的。然而现实世界没有完美的透镜。这主要是制造上的原因&#xff0c;因为制作一个“球形”透镜比制作一个数学上理想的透镜更容易。而且从机械方面也很难把透镜和成像仪保持平行。下面主要描述两种主要的透镜畸变并为他…

Python之No module named xxx类问题解决思路(三十)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

Java集合基础梳理(集合体系+ArrayList)

目录 Java集合体系 为什么要使用集合类 ? 如何选用集合? 哪些集合类是线程安全的&#xff1f;哪些不安全&#xff1f; 快速失败(fail-fast)和安全失败(fail-safe)的区别是什么&#xff1f; 遍历的同时修改一个List有几种方式 ArrayList 如何进行元素的遍历操作&#x…

【办公类-21-05】20240227单个word按“段落数”拆分多个Word(成果汇编 只有段落文字 1拆5)

作品展示 背景需求 前文对一套带有段落文字和表格的word进行13份拆分 【办公类-21-04】20240227单个word按“段落数”拆分多个Word&#xff08;三级育婴师操作参考题目1拆13份&#xff09;-CSDN博客文章浏览阅读293次&#xff0c;点赞8次&#xff0c;收藏3次。【办公类-21-04…

半小时到秒级,京东零售定时任务优化怎么做的?

导言&#xff1a; 京东零售技术团队通过真实线上案例总结了针对海量数据批处理任务的一些通用优化方法&#xff0c;除了供大家借鉴参考之外&#xff0c;也更希望通过这篇文章呼吁大家在平时开发程序时能够更加注意程序的性能和所消耗的资源&#xff0c;避免在流量突增时给系统…

在PyCharm中使用Git

安装Git CMD检查Git版本 打开cmd&#xff0c;输入git version&#xff0c;检查当前下载版本 配置git的user信息 在cmd中输入 git config --global user.name "用户名"git config --global user.email "用户邮箱"输入&#xff1a;git config --list&…

安卓平板主板_安卓平板电脑主板MTK联发科|高通|紫光展锐方案

安卓平板电脑主板选择了MTK联发科方案&#xff0c;并且可以选配高通或者紫光展锐平台方案&#xff0c;为用户提供更强劲的性能和定制化的服务。主板搭载了联发科MT6771处理器&#xff0c;采用12nm制程工艺&#xff0c;拥有八核Cortex-A73Coretex-A53架构&#xff0c;主频为2.0G…