首页 > 其他分享 >手撕Vue-Router-知识储备

手撕Vue-Router-知识储备

时间:2024-01-05 11:33:58浏览次数:35  
标签:Vue hash 路径 监听 我们 当中 home Router 储备


手撕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 值我们的容器显示的是什么。

手撕Vue-Router-知识储备_前端_02

我们可以看到我们的容器显示的是空的,那么我们怎么解决这个问题呢?我们可以在页面加载的时候,手动的触发一次 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, 好,这个时候我们的关键点就要来了:

手撕Vue-Router-知识储备_ecmascript_03

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

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

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

测试注意点

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

总结

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

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

标签:Vue,hash,路径,监听,我们,当中,home,Router,储备
From: https://blog.51cto.com/u_15652665/9111483

相关文章

  • 手撕Vue-Router-提取路由信息
    前言好了经过上一篇的学习,我们已经知道了如何监听Hash的变化,如何监听路径的一个变化,本篇我们就可以来实现我们自己的VueRouter了,那么怎么实现呢,在实现之前我们先来回顾一下官方的VueRouter是怎么使用的。VueRouter的使用首先需要去下载官方的VueRouter,如果是通过npm的......
  • 手撕Vue-Router-初始化路由信息
    前言经过上一节课的学习,我们已经完成了提取我们想要的路由信息数据格式,提取完毕了之后,接下来我们该干什么,接下来需要做的步骤就是监听路由的变化,保存当前的路由。那么就会遇到几个问题,就是怎么监听,怎么保存,我们先回到VueRouter的官方文档,点击右上角的API参考,然后拖动到底部,在底......
  • Vue3 自定义Hooks大全:一站式解决你的疑惑!
    前言不知道喜欢vue3的小伙伴和我是不是一样,刚上手vue3的时候对自定义hooks一脸懵逼,在一些视频网站学习的时候老师讲解到自定义hooks最喜欢用加减乘除来描述自定义hooks是咋用的,可能是我理解能力比较差吧,我看了这个加减乘除的自定义hooks之后感觉跟没看一样,还是一脸懵逼,......
  • VUE框架CLI组件化配置Router使用params传递参数机制解析------VUE框架
    <template><div><!--组件分为普通组件和路由组件--><divclass="s1"><h2>市区</h2><ul><!--写死信息方式传递--><!--<li><router-......
  • vue3 setup函数之数据
    setup中定义方法:exportdefault{name:'App',setup(){//定义方法functionedit(){}return{//方法与数据,必须要返回出去,不然不起作用。edit}}} setup中ref函数定义基本数据类型与对象数据类型:1.ref函数定义基......
  • vue全屏状态下退出登录仍保持全屏
    根本解决不要用Location等方式跳转,使用router方式跳转即可。router跳转会导致浏览器退出全屏吗在大多数情况下,当使用前端路由(例如VueRouter或ReactRouter)进行页面跳转时,浏览器通常不会退出全屏状态。前端路由是通过JavaScript在当前页面内进行导航,而不是通过浏览器的传统导......
  • 初识Sringboot3+vue3环境准备
    环境准备后端环境准备下载JDK17https://www.oracle.com/java/technologies/downloads/#jdk17-windows   安装就下一步下一步,选择安装路径 配置环境 环境JDK17+、IDEA2021+、maven3.5+、vscode后端基础:javaSE,javaWeb、JDBC、SMM框架(Spring+SpringMVC+MyBatis)、MyBatis-Plus前......
  • Blazor 混合开发_MAUI+Vue_WPF+Vue
    Blazor混合开发_MAUI+Vue_WPF+Vue背景混合开发的核心为什么必须使用wwwroot文件夹放置Web项目文件创建MAUI项目创建wwwroot文件夹服务注册创建_import.razor添加Main.razor组件修改MainPage.xaml文件创建WPF项目创建wwwroot文件夹服务注册创建_import.razor添......
  • VUE3 + Three.js 坑
    VUE3+Three.js坑1.问题描述将scene、camera、renderer、controls等变量用reactive变成响应式时,页面渲染会报错:three.module.js?5a89:24471UncaughtTypeError:'get'onproxy:property'modelViewMatrix'isaread-onlyandnon-configurabledatapropertyontheprox......
  • lottie 动画在 vue 中的使用
    前言最近我所负责的项目中,我采用了动画效果,并开始使用gif来实现。然而,在实践过程中,我发现gif格式的动画在git中出现了明显的锯齿感,这让我非常困扰。为了追求更完美的表现效果,我最终选择了lottie来实现我的动画需求。我深知动画效果的呈现对于用户体验至关重要,因此我非常认......