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

vue3使用vue-router路由(路由懒加载、路由传参)

zhezhongyun 2025-01-21 23:06 133 浏览

vue-router 是 vue的一个插件库

1. 专门用来实现一个SPA单页面应用

2 .基于vue的项目基本都会用到此库


SPA的理解

1) 单页Web应用(single page web application,SPA)

2) 整个应用只有一个完整的页面

3) 点击页面中的链接不会刷新页面, 本身也不会向服务器发请求

4) 当点击路由链接时, 只会做页面的局部更新


路由的理解

1) 什么是路由?

a. 一个路由就是一个映射(对应)关系(key:value)

b. key为路由路径path, value可能是function/component

2) 路由分类

a. 后台路由: node服务器端路由, value是function, 用来处理客户端提交的请求并返回一个响应数据

b. 前台路由: 浏览器端路由, value是component, 当请求的是路由path时, 浏览器端没有发送http请求, 但界面会更新显示对应的组件

3) 后台路由

a. 注册路由:

1. app.get(path, function(req, res))
2.router.get(path, function(req, res))

b. 当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据

4) 前端路由

a. 注册路由

{

path: '/home',

component: Home

},

b. 当浏览器的path变为/home时, 当前路由组件就会变为home组件


下载 终端执行命令: npm install vue-router

vue3 中使用 vue-router 需要4.x 版本,

安装完成后package.json 文件中会出现"vue-router": "^4.x.x"

npm install vue-router安装完成后:创建route文件夹和index.ts文件


index.ts文件代码:

@代表src路径

component: '@/views/Home/index.vue', 直接使用

component: () => import('@/views/Home/index.vue'), 路由懒加载写法
官网介绍路由懒加载:

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效。

Vue Router 支持开箱即用的动态导入,这意味着你可以用动态导入代替静态导入。


component (和 components) 配置接收一个返回 Promise 组件的函数,Vue Router 只会在第一次进入页面时才会获取这个函数,然后使用缓存数据。这意味着你也可以使用更复杂的函数,只要它们返回一个 Promise :

const Home = () =>

Promise.resolve({

/* 组件定义 */

})
component: Home,


routes配置项:

path: 路由定义的路径

name: 路由名称 > 对应 .vue组件的name

redirect: 重定向到某个路由

component: 组件

meta: 是一个用于描述路由元数据的对象。它允许你在定义路由时添加一些额外的信息,以便在路由导航过程中进行访问和处理。

通常,meta 被用来存储一些与路由相关的附加信息,例如页面标题、权限控制标识、页面级别的动画效果等。它可以在路由配置对象中的 meta 字段进行定义


这三种模式是用于配置路由的history、hash和memory模式。

  1. createWebHistory() 该模式使用浏览器的历史记录API来存储和管理路径。使用该模式时,路径的变化会在浏览器的历史记录中进行更新,用户可以使用浏览器的后退和前进按钮来导航。该模式需要服务器配置支持。
  2. createWebHashHistory() 该模式使用URL中的hash(#)来存储和管理路径。使用该模式时,路径的变化会在URL的hash值中进行更新,不会更新浏览器的历史记录。该模式适用于单页应用,可以在不支持HTML5 history API的浏览器中使用,但用户体验稍差。
  3. createMemoryHistory() 该模式是一种内存路径管理器,它将路径存储在内存中,不会更新浏览器的历史记录或URL。该模式适用于需要模拟路径变化的开发环境或测试环境,但不适用于生产环境。
import {
  createRouter,
  createWebHashHistory,
  RouteRecordRaw
} from "vue-router";
// createWebHashHistory,createWebHistory

const routes: RouteRecordRaw[] = [
  {
    path: '/',
    redirect: '/home',
  },
  {
    path: '/home',
    name: 'Home',
    // component: '@/views/Home/index.vue', @代表src
    component: () => import('@/views/Home/index.vue'),
    meta: {
      title: 'Home Page',
      roles: ['admin', 'admin1']
    }
  },
  {
    path: '/lx',
    name: 'Lx',
    component: () => import('@/views/Home/Lx.vue'),
    // 也可以使用props传参方式接收传来的参数
    props: (propsRouter) => {
      console.log('props >router', propsRouter)
      // 可以return query 也可以return params支持两种传参方式
      return propsRouter.query
    }
  },
  {
    path: '/lxb/:id/:title', // 提前定义params参数(可以定义多个)
    name: 'Lxb',
    component: () => import('@/views/Home/Lxb.vue'),
  },
]

export const router = createRouter({
  // 路由的history模式,共有三种模式,
  // createWebHistory、createWebHashHistory、createMemoryHistory
  history: createWebHashHistory(),// history: createWebHistory(),
  // 路由配置
  routes,
  // 是否严格匹配路由
  strict: true,
  // 路由跳转完成后,页面滚动行为
  scrollBehavior: () => ({ left: 0, top: 0 }),
})

main.ts文件代码:

import { router } from './route/index'
import { createApp } from 'vue'

const app = createApp(App)
app.use(router).mount('#app')

App.vue文件代码:

<template>
  <router-view />
</template>

<script>
import { defineComponent } from 'vue'
 // vue3.0版本语法
export default defineComponent({
  name: 'App',
})
</script>

标签导航和编程式导航:

router-link的to属性有三个可选参数,分别是tag、replace、append。 replace:是否使用replace()替换当前history记录,而不是push。用户点击浏览器的后退按钮时,不会返回上一个页面,而是回到replace()指定的页面。 tag:组件的名称,路由组件会在该组件中渲染。 append:是否使用push()追加到history记录,而不是替换当前的history记录。

replace和push的区别是replace替换当前的history记录,而push追加到history记录。 replace()和push()方法是针对history.pushstate方法的封装,针对不同的业务场景,使用不同的方法。 history.pushstate:该方法会向web应用的历史记录列表添加一个新的记录,并替换当前的历史记录。 history.replacestate:该方法会向web应用的历史记录列表添加一个新的记录,但不会替换当前的历史记录。 history对象是window对象的属性,history对象代表当前窗口的历史记录,可以使用history.pushstate()和history.replacestate()来修改历史记录。 history对象的属性和方法如下表所示。

在Vue Router中,query和params都可以用来传递参数,但是它们的使用场景和作用方式有所不同。

  1. query参数:query参数是附属于路由路径之后的参数,以?开头,多个参数用&连接。query参数是浏览器缓存的一部分,每次请求都会带有缓存的query参数。query参数会出现在请求的URL中,并且可以被浏览器的前进后退按钮所控制。

例如,对于路径/user/123,如果添加query参数{ query: 'foo' },则路径变为/user/123?query=foo。

  1. params参数:params参数是附属于路由路径内部的参数,用于在路径的不同部分之间传递参数。params参数不会出现在URL中,也不会被缓存,只能通过路由之间进行传递。

例如,对于路径/user/123/:id,如果传递的参数为{ name: 'john' },则路径变为/user/123/john。

query参数和params参数的主要区别如下:

  • query参数可以在浏览器历史记录中被保存和恢复,而params参数则不行。
  • query参数可以被浏览器的前进后退按钮控制,而params参数则不会被更新。
  • query参数可以被搜索引擎索引,而params参数则不会被索引。
  • query参数可以被排序和过滤,而params参数则不可以。

在使用query参数和params参数时,可以根据实际需求选择合适的方式。如果需要在不同路由之间传递参数,建议使用params参数;如果需要缓存和控制浏览器前进后退按钮,建议使用query参数。

注意编程式导航:query传参可以用path 也可以用name,params传参只能用name!

router.push({path: '/url',query: {}})

router.push({name: 'xxx',query: {}})

router.push({name: 'xxx',params: {}})


useRoute()和useRouter()是Vue Router中提供的两个用于获取路由信息的指令。

useRoute()指令可以用于组件内,通过解构赋值获取当前路由的路径、参数、query等信息。

useRouter()指令可以用于组件内,通过解构赋值获取路由相关的各种信息,如导航、路由匹配等。

import { useRoute, useRouter } from 'vue-router'

const route = useRoute() // 相当于vue2的this.$route

const router = useRouter() // 相当于vue2的this.$router


views文件夹下的Home文件夹下的index.vue文件代码:

<template>
  <div class="home">
    <h2>首页{{ title }}</h2>
    <!-- 模拟有权限时显示 -->
    <div v-if="roles.includes(role)">
      <h2>标签式导航(标签来定义导航链接)</h2>
      <!-- router-link 最终生成的是a标签 -->
      <router-link to="/lx">push跳转到练习页面</router-link>
      <br>
      <!-- replace 跳转讲不会缓存之前的路由页面了 -->
      <router-link replace to="/lx">replace跳转到练习页面</router-link>
      <br>
      <router-link to="/lx?title=101&id=1">跳转到练习页面(query传参)</router-link>
      <br>
      <router-link to="/lxb/id:2/title:102">跳转到练习b页面(params传参)</router-link>

      <h2>编程式导航</h2>
      <div @click="routerGo('lx')">跳转到练习页面(query传参)</div>
      <div @click="routerGo('lxb')">跳转到练习b页面(params传参)</div>

    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, onMounted, toRefs, } from 'vue'
import { useRoute, useRouter } from 'vue-router'

export default defineComponent({
  name: 'Home',
  setup() {
    const router = useRouter()
    const route: any = useRoute()

    const state = reactive({
      title: '',
      role: '', // 我的当前角色
      roles: [''],
      routerGo: (path) => {
        if (path === 'lx' || path === '/home/childA') {
          // query传参可以用path 也可以用name: Lx
          router.push({
            path: path,
            query: {
              title: '101',
              id: 1
            }
          })
          // router.replace
        } else {
          // params传参只能用name
          router.replace({
            // path: path + '/id:2/title:102',
            name: 'Lxb',
            params: {
              title: '102',
              id: 2
            }
          })
        }
      },
    })
    onMounted(() => {
      console.log('/home', route)
      state.title = route.meta.title
      state.roles = route.meta.roles
      // 模拟一个接口
      setTimeout(() => {
        const res = {
          code: 200,
          data: {
            token: '123456',
            userName: '吴彦祖',
            role: 'admin'
          }
        }
        state.role = res.data.role
      }, 0)
    })
    return {
      ...toRefs(state)
    }
  }
})
</script>

<style lang="less" scoped>
.home {
  color: pink;
  font-size: 14px;
}
</style>

views文件夹下的Home文件夹下的Lx.vue文件代码:

<template>
  <div style="font-size: 14px;">
    <h2>我是练习{{ title }}页面</h2>
    <div>id:{{ id }}</div>
    <div>props: {{props}}</div>
    <button @click="routerGoBack">返回首页</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, reactive, toRefs } from 'vue';
import { useRoute, useRouter } from 'vue-router'

// vue3.0语法
export default defineComponent({
  name: 'Lx',
  props: {
    id: {
      type: String,
      default: ''
    },
    title: {
      type: String,
      default: ''
    },
  },
  setup(props) {
    const route = useRoute()
    const router = useRouter()
    const state = reactive({
      id: '',
      title: '',
      routerGoBack: () => {
        router.go(-1) // go(-1)回到上一个路由
        // 也可以用router.replace('/home')跳回首页
      }
    })

    onMounted(() => {
      console.log('lx route',route)
      console.log('lx props',props)
      if (route.query) {
        state.id = route.query.id
        state.title = route.query.title
      }
    })

    return {
      props,
      ...toRefs(state)
    }
  },
})
</script>

views文件夹下的Home文件夹下的Lxb.vue文件代码:

<template>
  <div style="font-size: 14px;">
    <h2>我是练习b{{ route?.params?.title }}页面</h2>
    <div>id:{{ route?.params?.id }}</div>
    <button @click="routerGoBack">返回首页</button>
  </div>
</template>

<script lang="ts">
import { defineComponent, onMounted, reactive, toRefs } from 'vue'
import { useRoute, useRouter } from 'vue-router'

// vue3.0语法
export default defineComponent({
  name: 'Lxb',
  setup() {
    const route = useRoute()
    const router = useRouter()
    const state: any = reactive({
      routerGoBack: () => {
        router.replace('/home')
        // 由replace跳转进来的不可以使用router.go(-1) 路由栈是空的》回不到上一个路由
      }
    })

    onMounted(() => {
      console.log(route)
    })

    return {
      route,
      ...toRefs(state)
    }
  },
})
</script>

初始页面效果:


路由配置的 默认路径是/,重定向到/home路径

home页通过route取到meta上的roles权限数组 控制显示,title用于页面显示。

点击<router-link to="/lx">push跳转到练习页面后>页面效果:


成功跳入了/lx页面,由于默认router-link是push模式,点击返回首页使用router.go(-1) 回到上一个路由(首页)。

回到首页后再点<router-link replace to="/lx">replace跳转到练习页面>页面效果相同:但由于用的是replace跳转点击返回首页按钮go(-1)不能跳回首页了。

重新打开1个项目:点击<router-link to="/lx?title=101&id=1">跳转到练习页面(query传参)后>页面效果:



通过query形式传入的参数在route.query里可以取到

通过props 配置指定query传入的参数 在组件的props里可以取到。

点击返回首页

点击<router-link to="/lxb/id:2/title:102">跳转到练习b页面(params传参)>页面效果:

跳转至了/lxb路径页面,通过params形式传入的参数在route.params里可以取到


点击返回首页


编程式导航:点击跳转到练习页面(query传参)>页面效果:

编程式导航同样能将参数传入 只是和 router-link 写法不同,编程式导航更加灵活不局限于a标签,用js做跳转也方便传入变量等作为参数。


编程式导航:点击跳转到练习b页面(params传参)>与router-link跳转的页面效果一样:

编程式导航这里使用了replace跳入的该页面,所有回到首页用的是router.replace('/home'),因为replace不会记录之前的路由栈,go(-1)的形式找不到上一个路由,所有没法使用。我们使用replace('/home')指定路由跳转。


这一章知识量比较多,下一章再讲嵌套路由使用(多级路由)。


欢迎关注我的原创文章:小伙伴们!我是一名热衷于前端开发的作者,致力于分享我的知识和经验,帮助其他学习前端的小伙伴们。在我的文章中,你将会找到大量关于前端开发的精彩内容。

学习前端技术是现代互联网时代中非常重要的一项技能。无论你是想成为一名专业的前端工程师,还是仅仅对前端开发感兴趣,我的文章将能为你提供宝贵的指导和知识。

在我的文章中,你将会学到如何使用HTML、CSS和JavaScript创建精美的网页。我将深入讲解每个语言的基础知识,并提供一些实用技巧和最佳实践。无论你是初学者还是有一定经验的开发者,我的文章都能够满足你的学习需求。

此外,我还会分享一些关于前端开发的最新动态和行业趋势。互联网技术在不断发展,新的框架和工具层出不穷。通过我的文章,你将会了解到最新的前端技术趋势,并了解如何应对这些变化。

我深知学习前端不易,因此我将尽力以简洁明了的方式解释复杂的概念,并提供一些易于理解的实例和案例。我希望我的文章能够帮助你更快地理解前端开发,并提升你的技能。

如果你想了解更多关于前端开发的内容,不妨关注我的原创文章。我会不定期更新,为你带来最新的前端技术和知识。感谢你的关注和支持,我们一起探讨交流技术共同进步,期待与你一同探索前端开发的奇妙世界!

#前端##前端面试##怎样自学前端##web前端怎么入门学习##Web前端技术#

#vue3##vue##vue好用吗#

相关推荐

Python入门学习记录之一:变量_python怎么用变量

写这个,主要是对自己学习python知识的一个总结,也是加深自己的印象。变量(英文:variable),也叫标识符。在python中,变量的命名规则有以下三点:>变量名只能包含字母、数字和下划线...

python变量命名规则——来自小白的总结

python是一个动态编译类编程语言,所以程序在运行前不需要如C语言的先行编译动作,因此也只有在程序运行过程中才能发现程序的问题。基于此,python的变量就有一定的命名规范。python作为当前热门...

Python入门学习教程:第 2 章 变量与数据类型

2.1什么是变量?在编程中,变量就像一个存放数据的容器,它可以存储各种信息,并且这些信息可以被读取和修改。想象一下,变量就如同我们生活中的盒子,你可以把东西放进去,也可以随时拿出来看看,甚至可以换成...

绘制学术论文中的“三线表”具体指导

在科研过程中,大家用到最多的可能就是“三线表”。“三线表”,一般主要由三条横线构成,当然在变量名栏里也可以拆分单元格,出现更多的线。更重要的是,“三线表”也是一种数据记录规范,以“三线表”形式记录的数...

Python基础语法知识--变量和数据类型

学习Python中的变量和数据类型至关重要,因为它们构成了Python编程的基石。以下是帮助您了解Python中的变量和数据类型的分步指南:1.变量:变量在Python中用于存储数据值。它们充...

一文搞懂 Python 中的所有标点符号

反引号`无任何作用。传说Python3中它被移除是因为和单引号字符'太相似。波浪号~(按位取反符号)~被称为取反或补码运算符。它放在我们想要取反的对象前面。如果放在一个整数n...

Python变量类型和运算符_python中变量的含义

别再被小名词坑哭了:Python新手常犯的那些隐蔽错误,我用同事的真实bug拆给你看我记得有一次和同事张姐一起追查一个看似随机崩溃的脚本,最后发现罪魁祸首竟然是她把变量命名成了list。说实话...

从零开始:深入剖析 Spring Boot3 中配置文件的加载顺序

在当今的互联网软件开发领域,SpringBoot无疑是最为热门和广泛应用的框架之一。它以其强大的功能、便捷的开发体验,极大地提升了开发效率,成为众多开发者构建Web应用程序的首选。而在Spr...

Python中下划线 ‘_’ 的用法,你知道几种

Python中下划线()是一个有特殊含义和用途的符号,它可以用来表示以下几种情况:1在解释器中,下划线(_)表示上一个表达式的值,可以用来进行快速计算或测试。例如:>>>2+...

解锁Shell编程:变量_shell $变量

引言:开启Shell编程大门Shell作为用户与Linux内核之间的桥梁,为我们提供了强大的命令行交互方式。它不仅能执行简单的文件操作、进程管理,还能通过编写脚本实现复杂的自动化任务。无论是...

一文学会Python的变量命名规则!_python的变量命名有哪些要求

目录1.变量的命名原则3.内置函数尽量不要做变量4.删除变量和垃圾回收机制5.结语1.变量的命名原则①由英文字母、_(下划线)、或中文开头②变量名称只能由英文字母、数字、下画线或中文字所组成。③英文字...

更可靠的Rust-语法篇-区分语句/表达式,略览if/loop/while/for

src/main.rs://函数定义fnadd(a:i32,b:i32)->i32{a+b//末尾表达式}fnmain(){leta:i3...

C++第五课:变量的命名规则_c++中变量的命名规则

变量的命名不是想怎么起就怎么起的,而是有一套固定的规则的。具体规则:1.名字要合法:变量名必须是由字母、数字或下划线组成。例如:a,a1,a_1。2.开头不能是数字。例如:可以a1,但不能起1a。3....

Rust编程-核心篇-不安全编程_rust安全性

Unsafe的必要性Rust的所有权系统和类型系统为我们提供了强大的安全保障,但在某些情况下,我们需要突破这些限制来:与C代码交互实现底层系统编程优化性能关键代码实现某些编译器无法验证的安全操作Rus...

探秘 Python 内存管理:背后的神奇机制

在编程的世界里,内存管理就如同幕后的精密操控者,确保程序的高效运行。Python作为一种广泛使用的编程语言,其内存管理机制既巧妙又复杂,为开发者们提供了便利的同时,也展现了强大的底层控制能力。一、P...