手撕Vue-Router-知识储备

前言

本文是手写Vue-Router的第一篇,主要是对Vue-Router的知识储备,为后面的手写做准备。

那么 VueRouter 怎么实现呢?要想实现 VueRouter,首先要知道 VueRouter 它的本质是什么。

VueRouter 的本质

VueRoute 的本质是什么?VueRouter 的本质就是根据 "不同的 hash 值" 或者 "不同的路径地址", 将不同的内容渲染到 router-view 中。

再过去,我学习 VueRouter 的时候,知道 VueRouter 有两种模式,一种是 hash 模式,一种是 history 模式。那么这两种模式有什么区别呢?

hash 模式和 history 模式的区别

如果是 history 模式,那么我们的路径就是这样的:http://localhost:8080/home,如果是 hash 模式,那么我们的路径就是这样的:http://localhost:8080/#/home

了解了这些知识之后,所以实现 VueRouter 的核心关键点就在于如何监听 'hash''路径' 的变化, 再将不同的内容写到 router-view 中。

那么在实现 VueRouter 之前呢,我在给大家补充一下,如何监听 'hash''路径' 的变化。

如何监听 hash 或 路径 的变化

hash

首先我新建了一个 test.html 文件,然后在里面写了一个 div,然后给这个 div 设置了一个 idid 的值为 html

并且在页面当中添加了两个 a 标签,两个 a 标签的 href 分别跳转地址为,一个是 #/home,一个是 #/about

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a href="#/home">首页</a>
<a href="#/about">关于</a>
<div id="html"></div>
</body>
</html>

基本的结构我们搭建完毕,好了接下来我们怎么监听 hash 的变化呢?也非常的简单,其实在我们原生的 JS 当中,有一个 hashchange 事件,这个事件就是用来监听 hash 变化的(专门用于监听 hash 变化的)。

那么知道了监听 hash 变化的事件之后,我们怎么使用呢?我们可以给 window 绑定一个 hashchange 事件,然后在这个事件当中,有一个回调函数,主要 hash 变化之后,我们就可以在这个回调函数当中,获取到当前的 hash 值。

那么怎么验证它会执行这个回调函数呢,我们可以在这个回调函数当中,打印一下当前的 hash 值。

<script>
    window.addEventListener('hashchange', () => {
        console.log('当前的hash值发生了变化');
    });
</script>

好了,我们打开浏览器,然后点击首页,我们可以看到控制台打印了一句话,说明我们的 hash 值发生了变化,看到这一点就可以验证我的一个说法。

接下来我们要做的就是将内容渲染到 div 中,我们先简单的来将 hash 值写入到 div 中。

window.addEventListener('hashchange', () => {
    const currentHash = location.hash.slice(1);

    document.querySelector('#html').innerHTML = currentHash;
});

我们打开浏览器,点击首页,我们可以看到 div 中的内容变成了 home,点击关于,我们可以看到 div 中的内容变成了 about

将来我们是不是根据这个获取到对应的组件,然后将组件渲染到 div(某一个容器当中)中就可以了。

好了到这里我们的监听 hash 就可以,可以了之后还没完,可以了之后有没有这么一种情况,就是我们第一次打开页面的时候我们地址上面是没有 hash 值的,还有可能就是我们地址栏是有 hash 值的这种情况,是不是有可能,对吧,我们先来看看我们第一次打开页面的时候,有 hash 值我们的容器显示的是什么。

我们可以看到我们的容器显示的是空的,那么我们怎么解决这个问题呢?我们可以在页面加载的时候,手动的触发一次 hashchange 事件,这样我们就可以在页面加载的时候,将内容渲染到 div 中。

首先我们在 window 上面绑定一个 load 事件,然后在这个事件当中,我们手动的触发一次 hashchange 事件。

window.addEventListener('load', () => {
    const currentHash = location.hash.slice(1);
    document.querySelector('#html').innerHTML = currentHash;
});

我们打开浏览器,我们可以看到我们的容器当中显示的是 home,这样我们就解决了第一次打开页面的时候,我们的容器显示的是空的这个问题。

路径

到此为止,我们就可以监听 hash 的变化了,那么我们怎么监听路径的变化呢?我们可以使用 historypushState 方法,这个方法可以改变路径,然后我们就可以监听路径的变化了。

在看路径地址之前,我们先将基本的代码页面结构搭建一下,路径与之前的 hash 是不一样的,所以我们这里的 a 标签就不能使用 href 属性了,路径我们可以给 a 标签绑定一个事件,绑定一个方法然后在这个方法当中来改变路径。

页面样式的基本结构代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<a onclick="go('/home')">首页</a>
<a onclick="go('/about')">关于</a>
<div id="html"></div>
<script>
    function go(path) {
    }
</script>
</body>
</html>

定义了一个 go 方法,接收一个参数 path,接下来要做的事情就是根据这个 path 来改变路径,这个我们要怎么实现呢?这里我们可以借助一个 history 对象,在 history 对象当中有一个 pushState 方法,这个方法接收三个参数,第一个参数是 state,第二个参数是 title,第三个参数是 url

pushState 方法参数:

  • state:一个与指定网址相关的状态对象,popstate 事件触发时,该对象会传入回调函数。如果不需要这个对象,此处可以填 null。
  • title:新页面的标题,但是所有浏览器目前都忽略这个值,因此这里可以填 null。
  • url:新的网址,必须与当前页面处在同一个域。浏览器的地址栏将显示这个网址。

那么我们怎么使用呢?我们可以在 go 方法当中,调用 pushState 方法,然后将 path 传入到 pushState 方法当中,这样我们就可以改变路径了。

history.pushState(null, null, path);

好了,我们打开浏览器,点击首页,我们可以看到我们的路径变成了 http://localhost:8080/home,点击关于,我们可以看到我们的路径变成了 http://localhost:8080/about

没问题之后,我们再将内容渲染到 div 中,我们可以在 go 方法当中,获取到当前的路径,然后将路径写入到 div 中。

document.querySelector('#html').innerHTML = path;

我们打开浏览器,点击首页,我们可以看到我们的容器当中显示的是 home,点击关于,我们可以看到我们的容器当中显示的是 about

到此为止,我们就可以监听路径的变化了,好了知道这些内容之后,还有一个注意点需要给大家说一下:

注意点

我们先基于 IDEA 运行我们的项目,然后,点击一下首页这个时候我们的路径与容器内容都是 /home, 好,我们这个时候将地址复制一下,例如现在路径已经变为了 http://localhost:63342/home ,我们在点击一下关于,我们可以看到我们的路径变为了 http://localhost:63342/about, 好,这个时候我们的关键点就要来了:

正如上图所示,我们的路径变为了 http://localhost:63342/home, 但是容器的内容还是 about,这是为什么呢?所以说这个东西我们也需要进行同步一下,那么我们手动添加了路径那么它怎么知道我们有没有前进与后退呢?非常简单,其实在我们的原生 JS 当中,又有一个事件,这个事件就是 popstate 事件,通过这个事件,我们就可以监听到前进与后退的点击,通过这个事件监听了前进与后退的点击之后,它会执行一个回调函数,我们在这个回调函数当中,就可以处理之前的问题了。

更改我们的代码,我们可以在 window 上面绑定一个 popstate 事件,然后在这个事件当中,我们可以获取到当前的路径,然后将路径写入到 div 中。

window.addEventListener('popstate', () => {
    document.querySelector('#html').innerHTML = location.pathname;
});

测试注意点

我们打开浏览器,点击首页,我们可以看到我们的容器当中显示的是 home,点击关于,我们可以看到我们的容器当中显示的是 about,好,这个时候我们的关键点就要来了,我们点击一下浏览器的前进与后退,我们可以看到我们的容器当中显示的是 homeabout,这样我们就解决了这个问题。

总结

到此为止,我们了解了如何监听 hash 与路径的变化,并且了解到了如何监听前进与后退的点击,hash 与路径的变化。

本篇文章就到这里,感谢大家的阅读,如果有什么不足的地方,欢迎大家指出,我会及时的进行修改。

posted @   BNTang  阅读(401)  评论(4编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
  1. 1 总会有人离开 王巨星
  2. 2 月亮 孟凡明
  3. 3 迟里乌布
  4. 4 我只能离开 颜人中
  5. 5 达尔文 蔡健雅
  6. 6 夜色滚烫 叶明净
  7. 7 你的星环 路飞文
  8. 8 不再说话 三块木头
  9. 9 黄昏 粥粥和小伙/粥粥
  10. 10 爱不单行 刘大拿
  11. 11 心动贩卖机 PIggy
  12. 12 别来无恙 苏星婕
  13. 13 我们的歌 刘大拿
  14. 14 一直很安静 王贰浪
  15. 15 去有风的地方 清音
  16. 16 雪 Distance Capper/罗言
  17. 17 坏女孩 徐良/小凌
  18. 18 乐园 沧桑Cang333/虎皮蛋/曲甲
  19. 19 Ayo(Explicit) Chris Brown/Tyga
  20. 20 我的美丽feat.海洋Bo 海洋Bo/高睿
  21. 21 世事可爱 粥粥和小伙/粥粥
  22. 22 我记得 赵雷
  23. 23 我想牵着你的手 许嵩
  24. 24 人们都不懂 刘诺然
  25. 25 寻一个你(电视剧《苍兰诀》温情主题曲) TTTTTeehom
  26. 26 子莫格尼 杉和
  27. 27 Cat Cafe Shoffy
  28. 28 风停了雨停了我们还拥抱着 Superluckyqi
  29. 29 寂寞沙洲冷 于潼
  30. 30 三国恋 王巨星
  31. 31 达尔文 林俊杰
  32. 32 有些 颜人中
  33. 33 小模样 张小只ya
  34. 34 是否 程响
  35. 35 楼顶上的小斑鸠 队长
  36. 36 笑场 薛之谦
  37. 37 还是分开 张叶蕾
  38. 38 修炼爱情 林俊杰
  39. 39 二零三 毛不易
  40. 40 雅俗共赏 许嵩
  41. 41 Serendipity 古瑞斯Graps/Zakiya晴子
  42. 42 就让这大雨全都落下·2023 刘大拿
  43. 43 老男孩 筷子兄弟
  44. 44 有何不可 许嵩
  45. 45 缓缓 杜宣达
  46. 46 好久不见 陈奕迅
  47. 47 爱的魔法(Cover 金莎) 封茗囧菌
  48. 48 在你的身边 盛哲
  49. 49 带我去找夜生活 告五人
  50. 50 假面舞会 很美味
  51. 51 STAY The Kid LAROI/Justin Bieber
  52. 52 我好想睡觉的 无敌西红柿
  53. 53 日不落(温柔版)
  54. 54 恋爱画板 锦零
  55. 55 7710 好乐无荒/尹露浠
  56. 56 给你呀(又名:for ya) 蒋小呢
  57. 57 Love Story Taylor Swift
  58. 58 Plain Jane(Remix 13z) 鱼幼微
  59. 59 晚风 7opy/BT07
  60. 60 拜托 孙晨
  61. 61 乌梅子酱 李荣浩
  62. 62 南半球与北海道 范倪Liu
  63. 63 星河万里 Rom邢锐
拜托 - 孙晨
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 孙晨/朱贺

作曲 : 朱贺

巷口的那只猫还依然没着落

眼神还是一样迷茫的路过

那个想他的女人在异地漂泊

被命运束缚着他年少的轻狂呢

他想要飞拜托别让他受太多的罪

他又不是没有勇气去面对那么卑微

他想去追就放下该放的让他去追

他说如果那样一定很美

拜托别让他一番努力后换来是奢求

对他好点吧他舍得让你走

拜托别让他整夜都想着怎么才能够

别等他老了都不敢回头

他想要飞拜托别让他受太多的罪

他又不是没有勇气去面对那么卑微

他想去追就放下该放的让他去追

他说如果那样一定很美

拜托别让他一番努力后换来是奢求

对他好点吧他舍得让你走

拜托别让他整夜都想着怎么才能够

别等他老了都不敢回头

拜托别让他一番努力后什么都没有

他说就拼吧干了这杯酒

拜托别让他整夜都想着怎么才能够

来生做春风 流浪又自由

点击右上角即可分享
微信分享提示