Posted in

手写实现 vue-router(超详细思路+代码) – 掘金_AI阅读总结 — 包阅AI

包阅导读总结

1.

关键词:vue-router、hash 模式、手写实现、路由配置、组件封装

2.

总结:本文主要介绍了手写实现 vue-router 简化版的过程,以 hash 模式实现网址跳转改变,涉及路由配置、router-link 和 router-view 组件的实现,创建 Router 对象管理路由,阐述了相关原理和代码实现。

3.

主要内容:

– 手写 vue-router 简化版,以 hash 模式实现网址跳转

– App.vue 中使用 router-link 和 router-view

– router/index.js 进行路由配置

– 理解 app.use

– 插件自带 install 方法,在 app.use 中自动执行

– 创建 Router 对象管理路由

– 具备 install 方法,将对象挂载在 app 上,constructor 进行配置加载

– app.component 注册全局组件 router-link 和 router-view

– router-link 和 router-view 的实现

– router-link 本质是 a 标签,使用插槽接收文字,注意 hash 模式

– router-view 需动态渲染组件和寻找正确组件,使用 component 组件和 map 对象

– createWebHashHistory 和 createRouter 函数

– createWebHashHistory 监听网址改变并返回 hash 值

– createRouter 返回 new Router

思维导图:

文章地址:https://juejin.cn/post/7392412742097829940

文章来源:juejin.cn

作者:星辰中的维纳斯

发布时间:2024/7/17 13:32

语言:中文

总字数:2458字

预计阅读时间:10分钟

评分:87分

标签:Vue.js,路由管理,前端开发,手写实现,组件开发


以下为原文内容

本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com

前言

今天来手写实现vue-router简化版,主要以hash模式来实现网址的跳转改变。
涉及到router-link,router-view,路由配置主要目的是为了深刻的理解vue-router在路由加载背后到底做了些什么?话不多说开始进入今天的主题。

这是App.vue文件,感兴趣的小伙伴可以一起来实现

App.vue

<template>  <div>    <header>      <nav>        <router-link to="/">首页</router-link>        <router-link to="/about">About</router-link>      </nav>    </header>    <main>      <router-view></router-view>    </main>    <footer></footer>  </div></template><script setup></script><style lang="css" scoped></style>

router/index.js完整代码

import { createRouter, createWebHashHistory } from './grouter/index.js';import Home from '../pages/Home.vue';import About from '../pages/About.vue';const router = createRouter({    history: createWebHashHistory(),    routes: [        {            path: '/',            name: 'Home',            component: Home        }, {            path: '/about',            name: 'About',            component: About        }    ]})export default router;

理解app.use

一般我们在使用路由插件时是先进行npm i vue-router下载路由,然后在main.js中使用app.use导入router插件。想要手写vue-router,必须先搞懂app.use()干了一件什么事情。我们去官方文档下面看看。

image.png看完我们知道插件中自带一个install()方法,在app.use方法内会自动执行。所以我们只需要关注插件的实现即可。app.use()传送门 应用实例 API | Vue.js (vuejs.org)

创建Router对象来管理路由

useRouter方法和createRouter中我们可以明白,在vue-router中是有一个Router对象对着全局的路由进行管理。所以首先我们需要进行Router对象的创建,而对象的功能具备install方法,将Router对象挂载在app上。然后constructor(构造方法)需要进行history和routes的加载配置。让我们来逐一实现。

  1. 首先是install方法内,我们需要将整个路由对象暴露出去,然后使用createRouter方法来接受暴露的Router对象在默认导出,这里我们使用provideinject方法来对Router对象的暴露与接受。
  2. app将组件变为全局组件的方法,app.component来注册router-link和router-view

完整Router和useRouter代码,路径:router/grouter/index.js

const ROUTER_KEY = "__router__";export const useRouter = () => {        return inject(ROUTER_KEY);}class Router {    constructor(options) {                this.history = options.history;                this.routes = options.routes;                this.current = ref(this.history.url);                      this.history.bindEvent(() => {            this.current.value = window.location.hash.slice(1);        })    }        install(app) {                app.provide(ROUTER_KEY, this);        console.log("准备与vue对接");                app.component('router-link', RouterLink);        app.component('router-view', RouterView);    }}

router-link和router-view的实现

首先创建两个对应的vue文件,然后让我们来分别实现其中的功能。

router-link

<router-link to="/">首页</router-link>

router-link本质是使用了a标签,所以我们在进行router-link组件封装时, 直接使用<a></a>标签进行地址栏的跳转,to可以用defineProps来接受,但是router-link中的文字如何添加进入a标签中呢?这里我们使用到插槽Slots语法

image.png通过图片我们可以看到,只需要在<a></a>标签内添加插槽即可实现文字的接收,这里是Slots传送门,感兴趣的小伙伴可以自行查看:插槽 Slots | Vue.js (vuejs.org)
完成之后我们只需要注意我们使用的是hash模式,所以地址栏需要出现#

router-link完整代码 路径:router/grouter/RouterLink.vue

<template>  <a :href="'#' + props.to">    <slot></slot>  </a></template><script setup>const props = defineProps({  to: {    type: String,    required: true,  },});</script><style lang="css" scoped></style>

测试了一下发现没啥问题,地址可以改变。那么接下来就是router-view该如何实现

router-view

router-view需要的就相对繁琐一些,因为需要动态的根据地址hash的改变来进行组件的渲染,所以这里我们主要需要两个功能的实现。

  1. 组件的动态渲染
  2. hash地址的寻找正确的组件

首先思考功能1,v-if虽然可以动态渲染组件但是太多组件的话这要多少个v-else-if,所以排除,那有没有一种可以让我们只需要写一个组件然后让组件自动渲染不同的组件呢?你别说哦~~还真有。

image.png传送门:内置特殊元素 | Vue.js (vuejs.org)这个component组件还真可以满足我们的需求进行组件的动态渲染。那么我们接下来只需要考虑组件的寻找了。

我们可以创建一个mapRoutermap对象,然后在组件被加载时,进行当前router-view对象中的组件信息进行注册(set(path,component)),然后更改地址,只需要进行get方法就可以拿到对应的组件,但是注意有可能用户会输入错误代码所以需要进行校验

router-view完整代码 路径:router/grouter/RouterView.vue

<template>    <component :is="component"></component></template><script setup>import { useRouter } from "./index.js";import { computed } from "vue";const router = useRouter();const mapRouter = new Map();const reflectMapRouter = (router) => {  router.routes.forEach((route) => {         mapRouter.set(route.path, route.component);  });};reflectMapRouter(router);const component = computed(() => {  const nowRoute = mapRouter.get(router.current.value);    return nowRoute ? nowRoute : null;});</script><style lang="css" scoped></style>

createWebHashHistory&createRouter

createWebHashHistory两个事,1-监听网址的改变,2-返回地址中的hash值
createRouter就更简单了返回new Router(),

代码 路径 router/grouter/index.js

export const createRouter = (options) => {    return new Router(options);}export const createWebHashHistory = () => {    function bindEvent(fn) {        window.addEventListener('hashchange', fn);    }        return {        url: window.location.hash.slice(1) || '/',        bindEvent    }}

结语

本篇文章到此就基本全部完成了,文章全部为手写,所以可能会有一些打错字的情况,欢迎在评论区指正。又或者有小伙伴和大佬对本篇文章有别的看法和指导也欢迎在评论区指出,本人非常欢迎大佬和伙伴的建议和指正。-̗̀(๑ᵔ⌔ᵔ๑)

好了本篇文章就到此为止了,喜欢的话就点个赞和关注吧!