react-router原理

news2024/11/17 1:42:03

前端路由的原理

自己来监听URL的改变,改变url,渲染不同的组件(页面),但是页面不要进行强制刷新(a元素不行)。

  • hash模式,localhost:3000/#/abc
    • 优势就是兼容性更好,在老版IE中都可以运行
    • 缺点是有一个#,显得不像一个真实的路径
  • 通过HTML5中的history修改URL

1. URL的hash

原理:通过监听hashchange变化

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <a href="#/home">首页</a>
      <a href="#/about">关于</a>

      <div class="router-view"></div>
    </div>
    <script>
      // 获取router-view的DOM
      const routerViewEl = document.getElementsByClassName("router-view")[0];

      // 监听URL的改变
      window.addEventListener("hashchange", () => {
        switch (location.hash) {
          case "#/home":
            routerViewEl.innerHTML = "首页";
            break;
          case "#/about":
            routerViewEl.innerHTML = "关于";
            break;
          default:
            routerViewEl.innerHTML = "";
        }
      });
    </script>
  </body>
</html>

2. HTML5的history

history接口是HTML5新增的,常见方法和事件如下:

  • pushState: 使用新的路径
  • replaceState: 替换原来的路径
  • popstate事件
  • go: 向前或向后改变路径
  • forward: 向前改变路径
  • back: 向后改变路径

其中,pushState、replaceState、go、forward、back改变URL而不刷新页面,参考:https://blog.csdn.net/pj598707063/article/details/90720767

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <a href="/home">首页</a>
      <a href="/about">关于</a>

      <div class="router-view"></div>
    </div>

    <script>
      // 1.获取router-view的DOM
      const routerViewEl = document.getElementsByClassName("router-view")[0];

      // 获取所有的a元素, 自己来监听a元素的改变
      const aEls = document.getElementsByTagName("a");
      for (let el of aEls) {
        el.addEventListener("click", (e) => {
          e.preventDefault();
          const href = el.getAttribute("href");
          history.pushState({}, "", href);
          urlChange();
        });
      }

      // 执行返回操作时, 依然来到urlChange
      window.addEventListener("popstate", urlChange);

      // 监听URL的改变
      function urlChange() {
        switch (location.pathname) {
          case "/home":
            routerViewEl.innerHTML = "首页";
            break;
          case "/about":
            routerViewEl.innerHTML = "关于";
            break;
          default:
            routerViewEl.innerHTML = "";
        }
      }
    </script>
  </body>
</html>

react-router

react-router的版本4开始,路由不再集中在一个包进行管理了,而是进行了分包:

  • react-router是router的核心代码
  • react-router-dom是用于浏览器的
  • react-router-native是用于RN应用的

提示:安装react-router-dom会自动安装react-router

1. react-router基础

在这里插入图片描述

2. NavLink

在这里插入图片描述

NavLink是对Link的一个封装,支持更多属性,例如exact、activeStyle、activeClassName(这个属性的默认值为active)等

3. 动态路由

<NavLink to={`/detail/${id}`} activeClassName="link-active">详情</NavLink>
// const match = this.props.match;
// console.log(match.params);

<NavLink to={`/detail2?name=xiaoming&age=18`} activeClassName="link-active">详情2</NavLink>
// <h2>Detail2: {this.props.location.search}</h2>
<NavLink to={{
          pathname: "/detail3",
          search: "name=abc",
          state: info
         }} 
        activeClassName="link-active">
  详情3
</NavLink>
// to后面的对象将被保留到this.props.location中
// <h2>Detail3: {this.props.location.state.name}</h2>

4. redirect

import React, { PureComponent } from 'react'
import { Redirect } from 'react-router-dom';

export default class User extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      isLogin: true
    }
  }
  render() {
    return this.state.isLogin ? (
      <div>
        <h2>User</h2>
        <h2>用户名: coderwhy</h2>
      </div>
    ): <Redirect to="/login"/>
  }
}

5. 嵌套路由(19-45分)

在这里插入图片描述
对于嵌套路由,为了避免子路由里重父组件上的路径,可以通过basename处理,参考https://v5.reactrouter.com/web/api/BrowserRouter/basename-string

在这里插入图片描述

6. 手动路由跳转(19-59)

// App.jsx
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/profile" component={Profile} />
<Route path="/:id" component={User} />

因为About组件是在Route的component里渲染的,所以Route可以给About组件灌入很多属性,包括history、match等

// About.jsx
export default class About extends PureComponent {
  render() {
    console.log(this.props.route);
    const branch = matchRoutes(this.props.route.routes, "/about");
    console.log(branch);

    return (
      <div>
        <NavLink exact to="/about" activeClassName="about-active">企业历史</NavLink>
        <NavLink exact to="/about/culture" activeClassName="about-active">企业文化</NavLink>
        <NavLink exact to="/about/contact" activeClassName="about-active">联系我们</NavLink>
        <button onClick={e => this.jumpToJoin()}>加入我们</button>

        <Switch>
          <Route exact path="/about" component={AboutHisotry}/>
          <Route path="/about/culture" component={AboutCulture}/>
          <Route path="/about/contact" component={AboutContact}/>
          <Route path="/about/join" component={AboutJoin}/>
        </Switch>
      </div>
    )
  }
  jumpToJoin() {
    // console.log(this.props.history);
    // console.log(this.props.location);
    // console.log(this.props.match);
    this.props.history.push("/about/join");
  }
}
withRouter (19 - 1:21)

源码阅读:react-router-dom再调用了react-router
在这里插入图片描述

7. 路由统一管理react-router-config

对于上面的嵌套路由显得太零散,因此需要对路径进行统一管理。

// router.js
import Home from '../pages/home';
import About, { AboutHisotry, AboutCulture, AboutContact, AboutJoin } from '../pages/about';
import Profile from '../pages/profile';
import User from '../pages/user';

const routes = [
  {
    path: "/",
    exact: true,
    component: Home
  },
  {
    path: "/about",
    component: About,
    // 子路由
    routes: [
      {
        path: "/about",
        exact: true,
        component: AboutHisotry
      },
      {
        path: "/about/culture",
        component: AboutCulture
      },
      {
        path: "/about/contact",
        component: AboutContact
      },
      {
        path: "/about/join",
        component: AboutJoin
      },
    ]
  },
  {
    path: "/profile",
    component: Profile
  },
  {
    path: "/user",
    component: User
  }
]
export default routes;
// App.js
import { renderRoutes } from 'react-router-config';
import routes from './router';
render() {
	return (
		<div>{renderRoutes(routes)}</div>
	)
}
// About.js
import { renderRoutes } from 'react-router-config';
render() {
    return (
      <div>
        <NavLink exact to="/about" activeClassName="about-active">企业历史</NavLink>
        <NavLink exact to="/about/culture" activeClassName="about-active">企业文化</NavLink>
        <NavLink exact to="/about/contact" activeClassName="about-active">联系我们</NavLink>
        <button onClick={e => this.jumpToJoin()}>加入我们</button>

        {/* <Switch>
          <Route exact path="/about" component={AboutHisotry}/>
          <Route path="/about/culture" component={AboutCulture}/>
          <Route path="/about/contact" component={AboutContact}/>
          <Route path="/about/join" component={AboutJoin}/>
        </Switch> */}
		// 因为父组件是通过renderRoutes渲染的,所以能够拿到this.props.route
        {renderRoutes(this.props.route.routes)}
      </div>
    )
  }

react-router-config

参考链接:react-router

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

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

相关文章

DNS配置

TCP/IP提供了通过IP地址来连接到设备的功能&#xff0c;但对用户来讲&#xff0c;记住某台设备的IP地址是相当困难的&#xff0c;因此专门设计了一种字符串形式的主机命名机制&#xff0c;这些主机名与IP地址相对应。 在IP地址与主机名之间需要有一种转换和查询机制&#xff0c…

CANopen | 对象字典OD 06 - 创建对象字典变量,通过TPDO定时发送

文章目录一、前言二、实验目的三、对象字典OD四、TPDO1定时发送tx_Value变量一、前言 该笔记的程序: github 二、实验目的 CANopen从站有一个变量tx_Value&#xff0c;映射到TPDO1上。接着&#xff0c;CANopen从站每1S发送一次TPDO1&#xff0c;将tx_Value发送出去。 三、…

PasteSpider之文件同步软件的介绍

作为PasteSpider系统中的一大特色&#xff0c;那就是文件的差量同步和配置同步。能够实现对不同需求的良好实现。 在网站https://www.pastecode.cn/下载文件同步软件后&#xff0c;完全解压到自己的文件夹内&#xff0c;然后双击“SpiderSyncFile”,如下图&#xff1a; 打开登陆…

Nginx模板自动化

背景 在日常工作中&#xff0c;我们经常需要创建Nginx配置文件的模板&#xff0c;以便在不同的环境中快速部署和配置Nginx服务器。然而&#xff0c;这样的任务通常需要重复性高、耗时长&#xff0c;且容易出错。为了加快这些任务的完成&#xff0c;并提高工作效率&#xff0c;…

C/C++开发,认识opencv各模块

目录 一、opencv模块总述 二、opencv主要模块 2.1 opencv安装路径及内容 2.2 opencv模块头文件说明 2.3 成熟OpenCV主要模块 2.4 社区支持的opencv_contrib扩展主要模块 2.5 关于库文件的引用 一、opencv模块总述 opencv的主要能力在于图像处理&#xff0c;尤其是针对二维图…

字节8年测试经验,送给想要学习自动化测试的同学6条建议

我的职业生涯开始和大多数测试人一样&#xff0c;开始接触都是纯功能界面测试。那时候在一家电商公司做测试&#xff0c;做了有一段时间&#xff0c;熟悉产品的业务流程以及熟练测试工作流程规范之后&#xff0c;效率提高了&#xff0c;工作比较轻松&#xff0c;也得到了更好的…

QML控件--Dial

文章目录一、控件基本信息二、控件使用三、属性成员四、成员函数五、信号一、控件基本信息 Import Statement&#xff1a;import QtQuick.Controls 2.14 Since&#xff1a;Qt 5.7 Inherits&#xff1a;Control 二、控件使用 Dial&#xff1a;是一个旋钮控件&#xff1b; im…

【权限维持】黄金白银票据隐藏账户C2远控RustDeskGotoHTTP

文章目录内网域&单机版-权限维持-基于用户-隐藏用户内网域-权限维持-基于服务TGT-黄金白银票据黄金方法&#xff1a;白银方法&#xff1a;内网域-权限维持-基于软件-GotoHTTP&RustDesk—无需安装C2 GotoHTTPC2 RustDesk 推荐内网域&单机版-权限维持-基于用户-隐藏用…

Plist文件是什么?

plist 文件是一种用于存储应用程序配置信息的文件格式&#xff0c;其中包含应用程序的各种设置和数据。在过去&#xff0c;plist 文件通常是以.plist 格式存储的。然而&#xff0c;随着时间的推移&#xff0c;人们开始使用.plistx 格式来存储更复杂的数据结构和数据。如果您需要…

MySQL日期时间函数汇总、时间格式转换方法

MySQL日期时间函数汇总、时间格式转换方法时间函数日期时间格式转换date_format函数EXTRACT()DATE_ADD()DATE_SUB()DATEDIFF函数时间函数 函数描述NOW()返回当前的日期和时间CURDATE()返回当前的日期CURTIME()返回当前的时间DATE()返回日期或日期/时间表达式的日期部分HOUR()获…

【遗传算法、粒子群、改进遗传算法】基于智能算法的电力系统电网最优规划方案的研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【从零开始学Skynet】工具篇(一):Ubuntu16.04环境搭建

一、Ubuntu系统下载 为了初学者使用方便&#xff0c;我们下载的是Ubuntu16系统的桌面版本&#xff1a;下载地址 二、VirtualBox虚拟机下载 去Virtualbox官网下载:Downloads – Oracle VM VirtualBox 点击这里进行下载&#xff0c;下载完之后点击客户端进行安装&#xff0c;安装…

ros2-foxy windows下安装流程

1.系统要求 本手册安装环境为win10 x64 请确保已在系统路径中安装PowerShell。 请确保网络的通畅性 2.环境安装部分 安装Chocolatey 方案1&#xff1a; 复制以下命令行&#xff0c;使用管理员权限打开PowerShell&#xff0c;复制粘贴大法到PowerShell&#xff0c;安装好ch…

YC-A11(原创)基于springboot,vue网上商城

绪论 课题的开发背景 随着计算机和网络的快速发展&#xff0c;并且越来越普及&#xff0c;互联网日益成为人们收集信息常用渠道&#xff0c;电子商务开始流行&#xff0c;一种全新的理念不断形成并且快速发展&#xff0c;像国内电商巨头淘宝、京东、苏宁易购、唯品会等电商平台…

筑牢合规营销“防火墙”,助力四环医药实现合规营销管理能力全面进阶 | 案例研究

四环医药控股集团有限公司&#xff08;以下简称“四环医药”&#xff09;是一家集药品研发、生产和销售于一体的集团化医药企业&#xff0c;公司现拥有心脑血管疾病、肝病治疗、提高机体免疫机能、代谢及抗感染等多领域100品种。四环医药强大的营销体系及独特营销模式确保了自身…

会画画的海龟,Python Turtle库详解(27)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 欢迎和猫妹一起&#xff0c;趣味学Python。 今日主题 介绍下Python的turtle库&#xff0c;这是一个可以画画的库&#xff0c;非常适合小孩子在屏幕上画画。 先学习基础知…

Python入门教程+项目实战-9.4节: 字符串的格式化

目录 9.4.1 理解格式化 9.4.2 使用f-string进行格式化 9.4.3 使用格式化符号进行格式化 9.4.4 使用format方法进行格式化 9.4.5 知识要点 9.4.6 系统学习python 9.4.1 理解格式化 同学们比较熟悉的是磁盘格式化&#xff0c;将磁盘格式化以后&#xff0c;磁盘中的文件全部…

第10章_多线程

第10章_多线程 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 我们之前学习的程序在没有跳转语句的情况下&#xff0c;都是由上至下沿着一条路径依次执行。现在想要设计一个程序…

Spring概述及IoC,DI的理解

目录 一、Spring 是什么&#xff1f; 1.1 什么是容器&#xff1f; 1.2 如何理解IoC&#xff1f; 1.3 理解Spring Ioc 1.4 DI是什么 1.5 回顾IoC&#xff0c;DI 1.6 IoC和DI的对比 一、Spring 是什么&#xff1f; 我们通常所说的 Spring 指的是 Spring Framework&#x…

不会写代码也能做自动化?推荐一款自动化测试神器

在软件测试这条道路上&#xff0c;大部分的职业技能发展道路都会是纯业务手工测试→自动化测试→性能测试→安全测试/测试开发。 但是却有着一部分人起初进入软件测试这一行看重的就是软件测试属于IT行业&#xff0c;门槛比较低&#xff0c;不需要代码基础。 这就导致了这一部…