百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

理解vue的use,手写 router vueuse有什么用

ztj100 2024-12-22 22:02 13 浏览 0 评论

前言

先随便聊聊 vue-router 中的一些知识点,一些考点。

  • router 初始化以及配置,就不过多赘述,但自己要牢记于心。
  • 前几天和大家提到的 路由守卫, 比如router.brforeEach 等一些常用的api。
  • 路由懒加载。
{
  path: '/about',
  component: () => import('./views/About.vue')
}

进行路由匹配的时候,这样使用 import 函数引入,只有匹配到才会进行加载,可以更快的看到首页。所以首页就需要直接在外边 import 关键字导入。

  • router-link router-view 。点击 router-link 后,可以跳到其他页面,好像和 a 标签一样。但是它可比 a 强多了,是个组件。router-view 也是个组件,根据相应的路由地址,把对应的组件显示到自己所在的位置。

它们两个是全局组件,但不是 vue 自带的,是需要在 main.js 中 .use 一下才可以使用。这个 .use 到底是怎么回事?今天就来一起看看。

基本准备

1. 项目搭建

<!-- about页面 -->
<template>
    <div>
        about
    </div>
</template>

<!-- home页面 -->
<template>
    <div>
        home
    </div>
</template>

创建页面级别的组件 Home.vue 以及 About.vue,写入这样一个简单的内容。

接着就是基本的创建 router文件夹下的 index.js 来配置这两个组件的路由,About 记得使用懒加载,这里不写出来了。

<template>
  <header>
    <nav>
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link>
    </nav>
  </header>
  <main>
    <router-view></router-view>
  </main>
</template>

最后在 App.vue 中用起来就行。

2. 了解 vue 组件

思考 router-link 组件是如何工作的呢?像 router -link 这样不需要引入的组件称为 全局组件 ,注册后可在任何地方直接访问。除了这个还有我们最熟悉的 自定义组件 ,就是我们一般会写在 components 文件夹下的一些组件,需要什么,写一个就行,但是需要显式引入并在组件中注册。最后还有像 transition 这样的内置组件,是 vue 自己提供的。

在 vue 中,使用什么东西来让组件变成为全局组件呢?这是组件的一种声明方式,使用 app.component('router-link', RouterLink)

当我们把 app.use(router) 注释掉后,发现没有了 router-link这个组件了,但是却还是可以看得到 router-link 中的 Home 以及 About 。这又是为什么呢?

当一个组件没有引入,不被支持的时候, dom 会把它当成一般标签来解析。

所以我们要搞明白 .use 到底做了什么?

vue 只负责 组件思想, mvvm 响应式 等核心,其他的交给生态系统,一起开源。vue-router 是vue 生态系统中的路由模块, vue 和它生态的对接,就是这个use方法

手写 router

import { createRouter } from './grouter/index'

现在我们就自己来写 router ,理解 router 。将原来的引入改为 grouter 文件夹下的 idnex ,在这来实现 router 中的 api 。

创建 RouterLink 和 RouterView 这俩个 vue 文件。

1. RouterLink.vue

<!-- RouterLink.vue -->
<template>
    <a :href="'#' + $props.to">
        <!-- 插槽 -->
        <slot />
    </a>
</template>

<script setup>
const props = defineProps({
    to: {
        type: String,
        required: true
    }
})

</script>

因为 router-link 本来渲染到页面也是 a 标签,所以使用 a 元素来创建一个超链接。href 属性通过 : 简写绑定动态值,它将一个井号 #和 to的值进行拼接,这样创建一个动态的链接。在单页应用中,当用户点击链接时,不会触发页面刷新,而是通过 JavaScript 更改 URL 并显示新的内容。

在子组件模板中,<slot> 标签表示了一个占位符,任何在子组件标签内部定义的内容都将被渲染到这个占位符的位置。这使得父组件可以根据需要自定义链接的显示内容,而无需修改子组件的代码。

2. RouterView.vue

在子组件模板中,<slot> 标签表示了一个占位符,任何在子组件标签内部定义的内容都将被渲染到这个占位符的位置。这使得父组件可以根据需要自定义链接的显示内容,而无需修改子组件的代码。
2. RouterView.vue
xml 代码解读复制代码<!-- RouterView.vue -->
<template>
     <component :is="component"></component>
</template>

<script setup>
import { computed } from 'vue'
import { useRouter } from './index.js';

const router = useRouter()
// console.log(router);

// router-view 动态组件 展示 依赖于 url 的变化
const component = computed(() => {
   const route = router.routes.find(
    (route) => route.path == router.current.value
   )
    return router? route.component : null

})

</script>

使用 <component> 标签,这是一个特殊的 Vue 标签,允许我们根据传入的 is 属性动态地渲染不同的组件。is 属性会返回当前应该渲染的组件。计算属性根据当前 URL 路径来决定渲染哪个组件。通过查找与当前 URL 路径匹配的路由配置,返回找到的路由配置中指定的组件。

RouterView.vue 负责根据 URL 渲染正确的页面。<a> 链接组件提供了一种简单的方式来创建导航链接。结合这两个组件,我们就可以构建一个基本的手写路由系统,它允许用户通过点击链接来导航到不同的页面,并且页面会根据 URL 路径的变化动态更新。

3. index.js

<!-- index.js -->
import RouterLink from './RouterLink.vue'
import RouterView from './RouterView.vue'
import { ref, inject } from 'vue'


// 单例的责任
export const createRouter = (options) => {
    return  new Router(options)
}

export const createWebHashHistory = () => {
    function bindEvents(fn) {
        window.addEventListener('hashchange', fn)
    }
    // history 对象
    return {
        url: window.location.hash.slice(1) || '/',
        bindEvents
    }
}

// 标记一下,router 要向全局暴露
const ROUTER_KEY = '__router__'

// use 开头的是一派  hooks  函数式编程
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.bindEvents(() => {
            // console.log('//////////')
            this.current.value = window.location.hash.slice(1) || '/'
        })
    }
    // use 调用 插件install
    install(app) {
        // 全局声明一个router 全局使用的对象
        app.provide(ROUTER_KEY, this)

        console.log('准备与vue 对接', app)
        app.component('router-link', RouterLink)
        app.component('router-view', RouterView)
    }

}

createWebHashHistory 函数创建一个哈希历史模式的路由历史管理器,它负责监听浏览器的 hashchange 事件并获取当前 URL 的哈希值。

ROUTER_KEY 是一个符号,用于在 Vue 应用程序上下文中标识路由器实例。这在 Vue 组件之间共享路由器实例,以便各个组件可以访问到相同的路由信息和相关的方法。确保整个应用中的所有组件都可以访问同一个路由器实例,而不需要在每个组件中显式传递路由器。

useRouter 函数利用 inject 函数从 Vue 组件的上下文中获取路由器实例。

Router 类是一个构造函数,用于创建路由管理器实例。constructor 方法接收 history 和 routes 作为参数,并初始化路由状态。install 方法用于将路由器实例注入到 Vue 应用程序中,并注册 RouterLink 和 RouterView 组件。

思路巩固

讲了这么些,最后总的来看看 vue-router 到底做了些什么事情。

1. 创建路由组件

RouterLink 负责渲染带有特定 href 的 <a> 标签,其中 href 包含当前路由路径。用户点击时,会改变浏览器 URL 的 hash 部分,触发页面内的导航。

RouterView 负责根据当前 URL 路径动态渲染与之对应的组件。它通过计算属性确定展示哪个组件。

2. 设置路由逻辑

createWebHashHistory 创建一个简单的哈希历史管理器,用于监听 hashchange 事件,并获取当前 URL 的哈希部分作为路由路径。

Router 类 负责管理路由状态,包括当前路径、注册的路由规则等。它还包含一个 install 方法,用于将路由器实例注入到 Vue 应用程序中,并注册全局组件 RouterLink 和 RouterView。

3. 集成到 Vue 应用

使用 createRouter 工厂函数创建路由器实例,并通过 app.use 方法安装到 Vue 应用中。这一步会将路由器实例注册到 Vue 的上下文中,并注册全局组件。

总结

我们首先回顾了一些关于 Vue Router 的基础知识,例如初始化配置、路由守卫、路由懒加载、router-link 和 router-view 的使用等。接着详细介绍了如何手动实现一个简化版的 Vue 路由器。手写一个简易版的 Vue Router 不仅有助于深入理解 Vue Router 的设计原理,还能加深对 Vue 框架的理解。 看完希望对你有帮助,一起加油。

相关推荐

如何将数据仓库迁移到阿里云 AnalyticDB for PostgreSQL

阿里云AnalyticDBforPostgreSQL(以下简称ADBPG,即原HybridDBforPostgreSQL)为基于PostgreSQL内核的MPP架构的实时数据仓库服务,可以...

Python数据分析:探索性分析

写在前面如果你忘记了前面的文章,可以看看加深印象:Python数据处理...

CSP-J/S冲奖第21天:插入排序

...

C++基础语法梳理:算法丨十大排序算法(二)

本期是C++基础语法分享的第十六节,今天给大家来梳理一下十大排序算法后五个!归并排序...

C 语言的标准库有哪些

C语言的标准库并不是一个单一的实体,而是由一系列头文件(headerfiles)组成的集合。每个头文件声明了一组相关的函数、宏、类型和常量。程序员通过在代码中使用#include<...

[深度学习] ncnn安装和调用基础教程

1介绍ncnn是腾讯开发的一个为手机端极致优化的高性能神经网络前向计算框架,无第三方依赖,跨平台,但是通常都需要protobuf和opencv。ncnn目前已在腾讯多款应用中使用,如QQ,Qzon...

用rust实现经典的冒泡排序和快速排序

1.假设待排序数组如下letmutarr=[5,3,8,4,2,7,1];...

ncnn+PPYOLOv2首次结合!全网最详细代码解读来了

编辑:好困LRS【新智元导读】今天给大家安利一个宝藏仓库miemiedetection,该仓库集合了PPYOLO、PPYOLOv2、PPYOLOE三个算法pytorch实现三合一,其中的PPYOL...

C++特性使用建议

1.引用参数使用引用替代指针且所有不变的引用参数必须加上const。在C语言中,如果函数需要修改变量的值,参数必须为指针,如...

Qt4/5升级到Qt6吐血经验总结V202308

00:直观总结增加了很多轮子,同时原有模块拆分的也更细致,估计为了方便拓展个管理。把一些过度封装的东西移除了(比如同样的功能有多个函数),保证了只有一个函数执行该功能。把一些Qt5中兼容Qt4的方法废...

到底什么是C++11新特性,请看下文

C++11是一个比较大的更新,引入了很多新特性,以下是对这些特性的详细解释,帮助您快速理解C++11的内容1.自动类型推导(auto和decltype)...

掌握C++11这些特性,代码简洁性、安全性和性能轻松跃升!

C++11(又称C++0x)是C++编程语言的一次重大更新,引入了许多新特性,显著提升了代码简洁性、安全性和性能。以下是主要特性的分类介绍及示例:一、核心语言特性1.自动类型推导(auto)编译器自...

经典算法——凸包算法

凸包算法(ConvexHull)一、概念与问题描述凸包是指在平面上给定一组点,找到包含这些点的最小面积或最小周长的凸多边形。这个多边形没有任何内凹部分,即从一个多边形内的任意一点画一条线到多边形边界...

一起学习c++11——c++11中的新增的容器

c++11新增的容器1:array当时的初衷是希望提供一个在栈上分配的,定长数组,而且可以使用stl中的模板算法。array的用法如下:#include<string>#includ...

C++ 编程中的一些最佳实践

1.遵循代码简洁原则尽量避免冗余代码,通过模块化设计、清晰的命名和良好的结构,让代码更易于阅读和维护...

取消回复欢迎 发表评论: