手把手教你构建一个前端路由

news2025/2/26 23:11:46

涉及知识点:location对象、history对象

文章目录

    • 基础概念
      • 什么是路由
      • 如何实现前端路由
      • 涉及问题
    • 前端路由实现方式
      • 1. hash方式
      • 2. history方式
      • 3. debug:本地起服务报错
    • 扩展:封装路由类Router
      • hash
      • history

基础概念

什么是路由

路由是一组映射关系,本质上来说是location.href和UI的映射关系

如何实现前端路由

修改location.href,而页面不会主动刷新,需要用js控制对应展示UI

涉及问题

  • 如何修改location.href
  • 何时改变UI
  • 如何浏览器前进/后退🔙事件

前端路由实现方式

在这里插入图片描述
通过hash和history的方式切换路由时都不会引起页面的刷新

1. hash方式

hash通过a标签默认的行为来改变location.hash
通过hashchange事件来监听location.hash改变,可以指定相应呈现内容
此外,还可以跳转到对应id的元素处

  <body>  
    <a href="#hash1">hash2</a>
    <a href="#hash2">hash3</a>
    <a href="#green">green</a>

    <div id="content">当前路由的内容为:</div>
    <div style="height: 1000px; background: red;"></div>
    <div id="green" style="height: 1000px; background: green;"></div>

    <script>
      const onHashChange = () => {
        const contentEl = document.getElementById('content')
        contentEl.innerHTML = window.location.hash
      }

      window.addEventListener('hashchange', onHashChange)
    </script>
  </body>

2. history方式

单页面应用,变换loctaion的hash,但是页面不会自动刷新,需要js指定要改变的UI
原理:调用 history对象的replaceState或者pushState方法来改变路由,手动改变对应UI样式

 <body>
    <button>nav1</button>
    <button>nav2</button>
    <button>nav3</button>

    <div id="content">当前路由的内容为:</div>

    <script>
      const onPopState = () => {
        const contentEl = document.getElementById('content')
        contentEl.innerHTML = window.location.pathname
      }

      // button 只会改变location.path,不会出发popstate实践,监听不到
      const buttonEls = document.getElementsByTagName('button')

      for (let btnEl of buttonEls) {
        // 1 改变location中路径
        btnEl.onclick = () => {
          window.history.pushState(
            { nav: btnEl.innerHTML },
            'title',
            '/' + btnEl.innerHTML,
          )

          // 2 手动改变UI
          onPopState()
        }
      }

      // 点击前进返回按钮时,会调用popstate.改变UI
      window.addEventListener('popstate', onPopState)
    </script>
  </body>

3. debug:本地起服务报错

在这里插入图片描述
原因:history路由中的popstate不支持file协议
解决步骤参考:https://blog.csdn.net/am123999/article/details/120582419

扩展:封装路由类Router

如何使用:class Router
注册:register(navName, fn)
执行:emit(navName)
初始化:init() 最初路由对应的UI

hash

  <body>
    <a href="#hash1">hash2</a>
    <a href="#hash2">hash3</a>
    <a href="#green">green</a>

    <div id="content">当前路由的内容为:</div>
    <div style="height: 1000px; background: red;"></div>
    <div id="green" style="height: 1000px; background: green;"></div>

    <script>
      class Router {
        routerList
        constructor() {
          this.routerList = {}

          window.onhashchange = () => {
            this.routerList[this.getHashName()]()
          }
        }

        getHashName() {
          return location.hash
        }

        register(navName, fn) {
          this.routerList[navName] = fn
        }

        emit(navName) {
          typeof this.routerList[navName] === 'function' &&
            this.routerList[navName]()
        }

        init() {
          this.emit('/')
        }
      }

      const router = new Router()

      router.register('#hash1', () => {
        console.log('当前hash为#hash1')
      })

      router.register('#hash2', () => {
        console.log('当前hash为#hash2')
      })

      router.register('#green', () => {
        console.log('当前hash为green')
      })

    </script>
  </body>

history

  <body>
    <a href="/">主页</a>
    <a href="nav1">nav1</a>
    <a href="nav2">nav2</a>
    <a href="nav3">nav3</a>

    <script>
      class Router {
        routerList
        constructor() {
          this.routerList = {}

          window.onpopstate = () => {
            this.routerList[this.getPathName()]()
          }
        }

        register(navName, fn) {
          this.routerList[navName] = fn
        }

        getPathName() {
          return location.pathname
        }

        emit(navName) {
          history.pushState({ nav: navName }, null, navName)
          typeof this.routerList[navName] === 'function' &&
            this.routerList[navName]()
        }

        init() {
          this.emit('/')
        }
      }

      // 使用
      const router = new Router()
      // 注册函数和路由

      router.register('/', () => {
        console.log('切换到主页')
      })

      router.register('nav1', () => {
        console.log('切换到nav1')
      })

      router.register('nav2', () => {
        console.log('切换到nav2')
      })

      router.register('nav3', () => {
        console.log('切换到nav3')
      })

      router.init()

      const aEls = document.getElementsByTagName('a')

      for (const aEl of aEls) {
        aEl.onclick = (e) => {
          e.preventDefault()
          router.emit(e.target.getAttribute('href'))
        }
      }
    </script>
  </body>

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

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

相关文章

深度学习入门(9)神经网络Affine与Softmax层的计算图表示方式及其误差反向传播的代码实现

《深度学习入门》系列文章目录 深度学习入门 (1)感知机 深度学习入门&#xff08;2&#xff09;神经网络 深度学习入门&#xff08;3&#xff09;神经网络参数梯度的计算方式 深度学习入门&#xff08;4&#xff09;【深度学习实战】无框架实现两层神经网络的搭建与训练过程 深…

MySQL 进阶篇1.0 索引 SQL优化 视图 锁

01-课程介绍 02-存储引擎-MySQL体系结构 03存储引擎-简介 查询建表语句 --默认存储引擎:InnoDBshow create table account; 查询当前数据库支持的存储引擎show engines; 04存储引擎-InnoDB介绍 开关为"ON": 表示每个innodb引擎的表都有一个idb表共享文件 …

Focal Self-attention for Local-Global Interactions in Vision Transformers

目录 Abstract 1. Introduction 2. MEthod 2.1 Model architecture 2.2 Focal self-attention 2.2.1 Window-wise attention 2.2.2 Complexity analysis 2.3 Model configuration 3. Related work 4. Experiments 4.1 Image classification on ImageNet-1K 4.…

26. [Python GUI] PyQt5中拖放详解之拖放动作

PyQt5的拖放动作 1. 什么是拖放动作 拖放动作是指用户希望怎样处理拖放的数据&#xff0c;比如移动、复制、还是创建由目标到源的链 接等。 拖放动作由 Qt::DropAction 枚举描述&#xff1a; 2. 可能的拖放动作&#xff0c;实际的拖放动作&#xff0c;建议的拖放动作 可能的…

有什么制作网页的工具软件好用呢?

我们进行制作网页之前&#xff0c;都会找一些制作网页的工具软件&#xff0c;俗语有说“工欲善其事&#xff0c;必先利其器&#xff0c;所以找一款好的的工具软件可以对制作网页的过程提供很大帮助。那么有什么制作网页的工具软件呢&#xff1f; 制作网页的方式有哪些&#xff…

如何计算神经网络参数的个数?

目录 1. 卷积层 2. 分类层 3. 计算 LeNet 网络的参数个数 神经网络随着层数的加深&#xff0c;网络参数的个数会越来越多&#xff0c;小的网络有成千上万个参数&#xff0c;大的可以达到千万个网络参数。 所以应该如何计算神经网络参数的个数&#xff1f; 图像分类的神经网…

分享五款没什么名气却意外好用的软件

噔噔噔噔&#xff0c;作为一个黑科技软件爱好者&#xff0c;电脑里肯定是不会缺少这方面的东西&#xff0c;今天的5款优质软件闪亮登场了。 1.密码管理工具——RoboForm 这是一款密码管理的小插件&#xff0c;相信很多人都曾被各种各样的密码记忆弄得心力交瘁过&#xff0c;尤…

全国公务员考试:行测篇01《资料分析》

文章目录导读一、统计术语1.1、基期和现期1.2、增长量1.3、增长率1.4、例题1.5、年均增长量1.6、年均增长率1.7、同比和环比1.8、比重1.9、倍数1.10、平均数1.11、百分数1.12、成数1.13、翻番1.14、顺差和逆差1.15、GDP1.16、三大产业1.17、恩格尔系数和基尼系数1.18、五年计划…

【吴恩达机器学习笔记】六、过拟合及正则化

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为学习吴恩达机器学习视频的同学提供的随堂笔记。 &#x1f4da;专栏简介&#xff1a;在这个专栏&#xff0c;我将整理吴恩达机器学习视频的所有内容的笔记&…

JSON Web Token

目录1. 概念1. JWT 概述2. session认证流程2. JWT认证流程2. 使用JWT1. 获取令牌2. 验证令牌3. 封装工具类3. Springboot整合JWT1. 项目搭建2. 使用JWT3. 优化代码1. 概念 1. JWT 概述 JWT&#xff1a; 概念&#xff1a; 通过 JSON 形式作为 Web 应用中的令牌&#xff0c;用于…

[附源码]计算机毕业设计springboot贷款申请审核管理系统论文

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

「Vue3」手把手教你使用 Vite 快速搭建项目

本项目选型默认使用vue3 typescript vite 1. 使用vite初始化项目 vite创建地址&#xff0c;创建完成后有一个基本的项目结构了&#xff0c;如下图 2. 配置vite.config.ts&#xff0c;配置详解 import { defineConfig } from viteimport path from path;import vue from …

【PS-6】视图操作

目录 旋转视图工具 选项栏中的“滚动所有窗口 用【空格键】移动视图 将图片放大缩小的方法 1、缩放工具 2、通过鼠标右键对画面进行放大或缩小 3、【细微缩放】按钮 4、通过【CTRL /-】放大缩小 5、窗口→导航器 旋转视图工具 此工具常用于与数位板的结合使用 位置&…

北大惠普金融指数-匹配企业绿色创新指数2011-2020年:企业名称、年份、行业分类等多指标数据

1、数据来源&#xff1a;北京大学数字金融中心、国家统计局、国家专利产权局等部门公开数据 2、时间跨度&#xff1a;2011-2020年 3、区域范围&#xff1a;全国 4、指标说明&#xff1a; 中国内地31个省&#xff08;直辖市、自治区&#xff0c;简称“省”&#xff09;、337…

Rust机器学习之Linfa

Rust机器学习之Linfa 众所周知&#xff0c;Python之所以能成为机器学习的首选语言&#xff0c;与其丰富易用的库有很大关系。某种程度上可以说是诸如numpy、pandas、scikit-learn、matplotlib、pytorch、networks…等一系列科学计算和机器学习库成就了Python今天编程语言霸主的…

【MAX7800实现KWS20 demo演示】

【MAX7800实现KWS20 demo演示】1. 概述2. 关键字定位演示2.1 构建固件&#xff1a;2.2 选择板卡2.3 MAX78000 EVKIT2.3.1 MAX78000 EVKIT下载程序2.3.2 MAX78000 EVKIT 跳线设置2.3.3 MAX78000 EVKIT 操作2.4 MAX78000 Feather2.4.1 MAX78000 Feather羽毛板下载固件2.4.2 MAX78…

IBM MQ MQCSP

一&#xff0c;概念 1.1 用途 用途&#xff1a;MQCSP 结构使授权服务能够验证用户 ID 和密码。您在 MQCONNX 调用上指定 MQCSP 连接安全参数结构。 警告&#xff1a;在某些情况下&#xff0c;客户端应用程序的 MQCSP 结构中的密码将以纯文本形式通过网络发送。要确保客户端应…

【学习笔记58】JavaScript面向对象

一、认识面向对象 &#xff08;一&#xff09;面向过程编程 按照程序执行的过程一步一步的完成程序代码 &#xff08;二&#xff09;面向对象编程 面向对象编程是一种编程的方式/模式官方&#xff1a;对一类具有相同属性和功能的程序代码抽象的描述&#xff0c;实现代码编程…

Triangle Attack: A Query-efficient Decision-based Adversarial Attack

Triangle Attack: A Query-efficient Decision-based Adversarial Attack 三角攻击:一种查询高效的基于决策的对抗性攻击 Abstract 基于决策的攻击对实际应用程序构成了严重的威胁&#xff0c;因为它将目标模型视为一个黑箱&#xff0c;只访问硬预测标签。最近已经做出了很大…

【计组】指令和运算1--《深入浅出计算机组成原理》(二)

一、计算机指令 1、指令 从软件工程师的角度来讲&#xff0c;CPU就是一个执行各种计算机指令&#xff08;Instruction Code&#xff09;的逻辑.。 这里的计算机指令&#xff0c;也可以叫做机器语言。 不同发CPU支持的机器语言不同&#xff0c;如个人电脑用的是Intel的CPU&a…