十四、使用 Vue Router 开发单页应用(2)

news2024/9/21 12:46:58

本章概要

  • 动态路由匹配
    • 查询参数
  • 路由匹配语法
    • 参数的自定义正则表达式
    • 可重复参数
    • 可选参数
  • 嵌套路由

14.2 动态路由匹配

实际项目开发时,经常需要把匹配某种模式的路由映射到同一个组件。例如,有一个 Book 组件,对于所有 ID 各不相同的图书,都可以使用这个组件来渲染,这可以使用路径中的动态段(dynamic segment) 来实现。
继续《十四、使用 Vue Router 开发单页应用(1)》的项目,修改 App.vue ,使用 router-link 组件添加两个导航链接。代码如下:

<template>
  <p>
    <router-link to="/">首页</router-link>
    <router-link to="/news">新闻</router-link>
    <router-link to="/books">图书</router-link>
    <router-link to="/videos">视频</router-link>
    <router-link to="/book/1">图书1</router-link>
    <router-link to="/book/2">图书2</router-link>
  </p>
  <router-view></router-view>
</template>

<script>
export default {
  name: 'App',
  components: {
  }
}
</script>

在 components 目录下新建 Book.vue wen文件。如下:

<template>
    <div>图书ID: {{ $router.params.id }}</div>
</template>

<script>
export default {
}
</script>

接下来编辑 router 目录下的 index.js 文件,导入 Book 组件,并添加动态路径 /book/:id 的路由配置,如下:

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '@/components/Home'
import News from '@/components/News'
import Books from '@/components/Books'
import Videos from '@/components/Videos'
import Book from '@/components/Book'

export default createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: '/',
      component: Home,
    },
    {
      path: '/news',
      component: News,
    },
    {
      path: '/books',
      component: Books,
    },
    {
      path: '/videos',
      component: Videos,
    },
    {
      path:'/book/:id',
      component:Book
    }
  ]
})

在终端窗口执行 npm run serve 命令,运行项目,打开浏览器,出现 图书1和图书2链接,单击其中任意一个。结果如下:
在这里插入图片描述

在同一个路由中可以有多个参数,它们将映射到 route.params 中的相应字段,如下表所示:

模式匹配路径route.params
/user/:username/user/evan{username:‘evan’}
/user/:username/post/:post_id/user/evan/post/123{username:‘evan’,post_id:‘123’}

除了 route.params 外,route 对象还提供了其它有用信息,如 route.query (如果 URL 中有查询参数)、route.hash 等。

14.2.1 查询参数

URL 中带有查询参数的形式为 /book?id=1,这在传统的 Web 应用程序中很常见,根据查询参数想服务端请求数据。在单页应用程序开发中,也支持路径中的查询参数。

修改 App.vue 文件

<template>
  <p>
    <router-link to="/">首页</router-link>
    <router-link to="/news">新闻</router-link>
    <router-link to="/books">图书</router-link>
    <router-link to="/videos">视频</router-link>
    <router-link to="/book?id=1">图书1</router-link>
    <router-link to="/book?id=2">图书2</router-link>
  </p>
  <router-view></router-view>
</template>

<script>
export default {
  name: 'App',
  components: {
  }
}
</script>

修改 Book.vue

<template>
    <div>图书ID: {{ $route.query.id }}</div>
</template>

<script>
export default {
}
</script>

修改 index.js

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '@/components/Home'
import News from '@/components/News'
import Books from '@/components/Books'
import Videos from '@/components/Videos'
import Book from '@/components/Book'

export default createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: '/',
      component: Home,
    },
    {
      path: '/news',
      component: News,
    },
    {
      path: '/books',
      component: Books,
    },
    {
      path: '/videos',
      component: Videos,
    },
    {
      path:'/book',
      component:Book
    }
  ]
})

运行项目,单击“图书1”链接。查询参数演示结果如下:
在这里插入图片描述

14.3 路由匹配语法

大多数应用程序使用静态路由(如/news)和动态路由(如/book/1)就可以满足应用的需求,不过 Vue Router 也提供了更加强大的参数匹配能力。要匹配任何内容,可以使用自定义参数正则表达式,方法是在参数后面的圆括号中使用正则表达式。

14.3.1 参数的自定义正则表达式

当定义一个如 “:id”的参数时,Vue Router 在内部使用正则表达式“([^/]+)”(至少有一个不是斜杠 / 的字符)从 URL 中提取参数。
假设有两个路由 /:orderId 和 /:productName ,它们将匹配完全相同的 URL ,要想区分它们,最简单的方法是在路径中添加一个静态部分来区分。代码如下:

const routes = [
  // 匹配 /o/3549
  { path:'/o/:orderId' },
  // 匹配 /p/books
  { path:'/p/:productName' }
]

假设要限定 orderId 只能是数字,而 productName 可以是任何值,那么在参数 orderId 后的圆括号中使用正则表达式来说明。代码如下:

const routes = [
  // /:orderId 只能匹配数字
  { path:'/o/:orderId(\\d+)' },
  // /:productName 匹配任何值
  { path:'/p/:productName' }
]

14.3.2 可重复参数

可以使用修饰符“*”(零个或多个)、“+”(一个或多个)将参数标记为可重复的。如下:

const routes = [
  // /:chapters -> 匹配 /one,/one/two./one/tow/three,etc
  { path:'/:chapters+' }
  // /:chapters -> 匹配 /,/one,/one/two./one/tow/three,etc
  { path:'/:chapters*' }
]

这将给出一个 params 数组而不是字符串,并且在使用命名路由时也需要传递一个数组。如下:

// given { path:'/:chapters*',name:'chapters' },
router.resolve({ name:'chapters',params:{chapters: [] } }).href
// 结果:/
router.resolve({ name: 'chapters',params:{ chapters:['a','b'] }}).href
// 结果:/a/b
// given { path:'/:chapters+',name:'chapters' }
router.resolve({ name:'chapters',params:{ chapters:[] } }).href
// 因为 chapters 是空,这将抛出一个错误

还可以通过将 “*”和“+”添加到右括号后,与自定义正则表达式结合使用。

const router = [
  // 只匹配数字
  { path:'/:chapters(\\d+)+' },
  { path:'/:chapters(\\d+)*' }
]

14.3.3 可选参数

还可以使用“?”将参数标记为可选的。如下:

const routers = [
  // 匹配 /users 和 /users/posva
  { path:'/users/:userId?' }
  // 匹配 /users 和 /users/42
  { path:'/users/:userId(\\d+)?' }
]

14.4 嵌套路由

在实际应用场景中,一个界面 UI 通常由多层嵌套的组件组合而成,URL 中的各段也按某种结构对应嵌套的各层组件。
在这里插入图片描述

路径 user/:id 映射到 User 组件,根据 ID 的不同,显示不同的用户信息。ID 为 1 的用户单击链接 user/1/profile ,将在用户1的视图中渲染 Profile 组件;单击 user/1/posts ,将在用户1的视图中渲染 Posts组件。

继续 14.2 节中的例子(将例子恢复为动态段),当单击“图书”链接时,以列表形式显示所有图书的书名,进一步单击单个书名链接,在 Books 视图中显示图书的详细信息。这可以通过嵌套路由来实现。
在 assets 目录下新建一个 books.js 文件,里面是图书数据。如下:

books.js

export default [
    { id: 1, title: '标题1', desc: '描述1' },
    { id: 2, title: '标题2', desc: '描述2' },
    { id: 3, title: '标题3', desc: '描述3' },
]

这里硬编码了图书数据,只是为了演示需要,真实场景中,图书数据应该是通过 Ajax 请求从服务端加载得到。
修改 Books.vue,以列表方式显示图书数据,添加导航链接,并使用 router-view 指定 Book 组件渲染的位置。如下:

Books.vue

<template>
    <div>
        <h3>图书列表</h3>
        <url>
            <li v-for="book in books" :key="book.id">
                <router-link :to="'/book/'+book.id">{{ book.title }}</router-link>
            </li>
        </url>
        <!-- Book 组件在这里渲染 -->
        <router-view></router-view>
    </div>
</template>

<script>
// 导入 Books 数组
import Books from '@/assets/books'
export default {
    data(){
        return{
            books:Books
        }
    }
}
</script>

注意删除 App.vue 中的图书1 和图书2 的 router-link 的配置。
修改 router 目录下的 index.js 文件,增加嵌套路由的配置。如下:

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '@/components/Home'
import News from '@/components/News'
import Books from '@/components/Books'
import Videos from '@/components/Videos'
import Book from '@/components/Book'

export default createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: '/',
      component: Home,
    },
    {
      path: '/news',
      component: News,
    },
    {
      path: '/books',
      component: Books,
      children: [
        { path: '/book/:id', component: Book }
      ]
    },
    {
      path: '/videos',
      component: Videos,
    },
  ]
})

说明:

  • 要在嵌套的出口(即 Books 组件中的 router-view)中渲染组件,需要在 routes 选项的配置中使用 children 选项。children 选项只是路由配置对象的另一个数组,如同 routes 本身一样,因此,可以根据需要继续嵌套路由。
  • 以“/”开头的嵌套路径被视为根路径。如果导航链接设置的是 /books/book/id 这种形式,那么这里配置路径时,需要去掉“/”,即 {path:‘book/:id’,component:Book}

Book.vue

<template>
    <!-- <div>图书ID:{{ $route.query.id }}</div> -->
    <div>图书ID:{{ $route.params.id }}</div>
</template>


<script>
export default {
}
</script>

在终端窗口中运行项目,打开浏览器,单击“图书”链接后,任选一本图书,结果如下:
在这里插入图片描述

在实际场景中,当单击某本图书链接时,应该向服务器发起 Ajax 请求来获取图书详细数据,于是想到在 Book 组件中通过生命周期钩子函数来实现,然而,这行不通。

因为当两个路由都渲染同一个组件时,如从 book/1 导航到 book/2 时,Vue 会复用先前的 Book 实例,比起销毁旧实例再创建新实例,复用会更加高效。但是这就意味着组件间的生命周期钩子不会再被调用,所以也就无法在生命周期构钩子中去根据路由参数的变化更新数据。

要对同一组件的路由参数更改做出响应,只需监听 route.params 即可。
修改 Book.vue ,当路由参数变化时,更新图书详细数据。如下:

Book.vue

<template>
    <p> 图书ID:{{ book.id }} </p>
    <p> 标题:{{ book.title }} </p>
    <p> 描述:{{ book.desc }} </p>
</template>

<script>
import Books from '@/assets/books'
export default {
    data() {
        return {
            book: {}
        }
    },
    created() {
        this.book = Books.find((item) => item.id == this.$route.params.id);
        this.$watch(
            () => this.$route.params,
            (toParams) => {
                console.log(toParams)
                this.book = Books.find((item) => item.id == toParams.id);
            }
        )
    }
}
</script>

说明
(1)只有路由参数发生变化时,route.params 的监听才会被调用,这意味着第一次渲染 Book 组件时,通过 route.params 的监听器是得不到数据的,因此在 created 钩子中先获取第一次渲染时的数据。当然,也可以向 watch 方法传入一个选项对象作为第3个参数,设置 immediate 选项参数为 true ,使监听器回调函数在监听开始后立即执行,即不需要在 created 钩子中先获取一次数据。如下:

created(){
  // this.book = Books.find((item) => item.id == this.$route.params.id);
  this.$watch(
    () => this.$route.params,
    (toParams) => {
      this.book = Books.find((item) => item.id == toParams.id);
    }
  )
}

(2)route.params 监听器回调函数的 toParams 参数表示即将进入的目标路由的参数,该函数还可以带一个 previousParams 参数,表示当前导航正要离开的路由的参数。

运行项目,单击不同的图书链接将显示对应图书的详细信息,如图:
在这里插入图片描述

除了监听 route 对象外,还可以利用 Vue Router 中的导航守卫(navigation guard):beforeRouteUpdate,可以把它理解为是针对路由的一个钩子函数。
修改 Book.vue 删除 route.params 监听器,改用 beforeRouteUpdate 来实现。如下:

<template>
    <p> 图书ID:{{ book.id }} </p>
    <p> 标题:{{ book.title }} </p>
    <p> 描述:{{ book.desc }} </p>
</template>

<script>
import Books from '@/assets/books'
export default {
    data() {
        return {
            book: {}
        }
    },
    beforeRouteUpdate (to) {
    this.book = null;
    this.book = Books.find((item) => item.id == to.params.id);
  }
}
</script>

beforeRouteUpdate 在当前路由改变,但是该组价被复用时调用,它有两个常用的参数。to 表示即将进入的目标路由位置对象;from 表示当前导航正要离开的路由位置对象。此处只用到了参数 to。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/60308.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MOOC 大数据Note

MOOC 大数据NoteSparkSpark 一个软件栈满足不同交互场景Lineage 血缘关系创建 转换 动作ShuffleMapStageSpark的部署和应用方式RDD操作分为转换&#xff08;Transformation&#xff09;和动作&#xff08;Action&#xff09;两种类型&#xff0c;下列属于动作&#xff08;Actio…

开发工具——gcc/g++

开发工具gcc/g 完成代码的编写完后&#xff0c;要形成可执行程序&#xff0c;需要编译工具进行对代码的编译。 C语言的编译工具是gcc&#xff0c;c的编译工具是g。 如果g没有的话&#xff0c;可以切换到root执行命令yum install -y gcc-c C语言和C的编译&#xff1a; gc…

「点燃我,温暖你」用Python制作一个动态爱心效果

最近「点燃我&#xff0c;温暖你」这部剧非常火&#xff0c;讲述的是程序员的爱情故事。 其中陈飞宇饰演的男主李峋&#xff0c;在剧中用程序做出的爱心跳动效果&#xff0c;非常炫。 网上各个大佬也是纷纷给出看法&#xff0c;综合就是不太可能用C语言来实现的。 大概率是AE…

Reg注册表读写

在Windows 95及其后继版本中&#xff0c;采用了一种叫做“注册表”的数据库来统一进行管理&#xff0c;将各种信息资源集中起来并存储各种配置信息。按照这一原则&#xff0c;Windows各版本中都采用了将应用程序和计算机系统全部配置信息容纳在一起的注册表&#xff0c;用来管理…

Java内存溢出故障案例及Linux内存机制探究

文章目录Java内存溢出故障案例及Linux内存机制探究OOM Killer触发机制分析如何避免系统触发OOM Killer这部分内容属于demo案例分享&#xff0c;解决线上运维问题&#xff0c;思路是最重要的 Java内存溢出故障案例及Linux内存机制探究 这是一个线上数据分析应用故障案例&#…

Java—反射

文章目录什么是反射反射定义java创建对象的三个阶段反射过程反射第一步&#xff1a;获取类对象获取类对象的三种方式反射第二步&#xff1a;获取类信息如何获取类信息&#xff1f;1、获取成员变量&#xff1a;2、获取方法&#xff1a;3、获取构造器反射第三步&#xff1a;使用反…

vue学习笔记——简单入门总结(四)

文章目录1.Vue3的特性和变化1.1.创建vue3项目1.2.分析main.js变化&#xff1a;1.3.setup--组合式api的开端1.4.ref函数和reactive函数&#xff1a;1.5.watch监视属性1.5.watchEffect函数1.6.vue3生命周期&#xff1a;1.Vue3的特性和变化 1.1.创建vue3项目 1.这里我们使用脚手架…

RegAD-Registration based Few-Shot Anomaly Detection论文学习

摘要 本文为少样本异常检测&#xff08;FSAD&#xff09;&#xff0c;这是一种实用但尚未被研究的异常检测&#xff08;AD&#xff09;&#xff0c;少样本意味着在训练中只为每个类别提供有限数量的正常图像。 现有的少样本异常检测的研究主要使用的是 一类别一模型 学习范式…

李宏毅《DLHLP》学习笔记7 - Voice Conversion

视频链接&#xff1a;https://www.youtube.com/watch?vJj6blc8UijY&listPLJV_el3uVTsO07RpBYFsXg-bN5Lu0nhdG&index9&ab_channelHung-yiLee 课件链接&#xff1a;https://speech.ee.ntu.edu.tw/~tlkagk/courses/DLHLP20/Voice%20Conversion%20(v3).pdf 1. 语音转…

JAVA+MySQL 图书馆借阅信息管理系统

图书馆是当下很多大学生和有志青年学习和借阅图书的场所,图书馆每天都有大量的人员需要接待,如何能够更好的对用户的这些借阅信息进行信息化的管理是当下大多数图书馆管理人员所关心的问题 本系统是通过JAVA和MYSQL来进行开发的,通过本系统可以对图书馆内的图书信息,用户信息以…

基于PCIe的NVMe协议在FPGA中实现方法

NVMe协议是工作在PCIE的最上层协议层的&#xff0c;故需要先搞清楚PCIE。本文基于Xilinx的UltraScale&#xff0c;开发工具为Vivado2021.2。学习中以spec为主&#xff0c;其它资料辅助参考(重点介绍学习方法及资料&#xff0c;有时间再加细节)。请勿转载&#xff01; 1 PCIe学…

基于PHP+MySQL青年志愿者服务管理系统的设计与实现

志愿者管理系统能够通过互联网得到广泛的、全面的宣传,让尽可能多的人积极的参加到志愿者行列中来,不仅为需要的人提供了服务,而且锻炼了自己,志愿者是一个对社会和自己以及需要帮助的人都有很多好处的事情 PHP青年志愿者服务网站是一个公益类型的网站,系统通过PHp&#xff1a;…

HK1 BOX刷入 Armbian系统作为服务器

HK1 BOX刷入 Armbian系统作为服务器 1 安装Armbian到EMMC 硬件 HK1 BOX s905 x3 固件版本选择 Armbian_23.02.0_Aml_s905x3_bullseye_5.15.80_server_2022.12.01用usb启动&#xff0c;tf/sd有的设备不行&#xff0c;有干扰&#xff0c;有可能从TF卡无法启动系统。 用usb启…

Grid 布局实现九宫格图片动画

前言 &#x1f44f;Grid 布局实现九宫格&#xff0c;background-position设置背景图像起始位置&#xff0c;速速来Get吧~ &#x1f947;文末分享源代码。记得点赞关注收藏&#xff01; 1.实现效果 2.实现步骤 定义css变量&#xff1a;九宫格中每个宫格的长/宽为w&#xff0c…

Kafka - 14 Kafka消费者 | 分区的分配策略及再平衡 | Range | RoundRobin | Sticky | CooperativeSticky

文章目录1. 分区的分配以及再平衡2. Range 分区分配以及再平衡3. RoundRobin 分区分配以及再平衡4. Sticky 分区分配以及再平衡1. 分区的分配以及再平衡 一个consumer group中有多个consumer组成&#xff0c;一个 topic有多个partition组成&#xff0c;现在的问题是&#xff0…

【Python自然语言处理】规则分词中正向、反向、双向最大匹配法的讲解及实战(超详细 附源码)

需要源码和字典集请点赞关注收藏后评论区留言私信~~~ 一、规则分词 规则分词核心内容是建立人工专家词典库&#xff0c;通过将语句切分出的单词串与专家词典库中的所有词语进行逐一匹配&#xff0c;匹配成功则进行对象词语切分&#xff0c;否则通过增加或者减少一个字继续比较…

文件或者文件夹的忽略

文件或者文件夹的忽略 编辑项目的时候&#xff0c;将一些临时文件或者插件可以忽略上传到项目库中去。 追踪中的文件&#xff0c;不能被忽略。 首先的创建.gitignore文件&#xff0c;并且该文件需要放到项目的根目录下 接着&#xff0c;打开.gitignore文件 windows中 open d…

软件测试——分类

测试分类 一、按照测试对象划分 1、界面 界面测试UI测试 &#xff08;1&#xff09;测试软件界面元素完整性&#xff0c;正确性&#xff0c;一致性 &#xff08;2&#xff09;软件界面排版布局合理、字体、颜色 &#xff08;3&#xff09;测试界面的自适应性&#xff0c;界面…

1549_AURIX_TC275_SCU系统中的CCU模块

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) 从这一份笔记开始看一下SCU系统&#xff0c;其实这个是一个功能组合&#xff0c;其中的一个小模块又叫做SCU。因此&#xff0c;在名称上可能会有一点点绕。近段时间看相关的资料比较多&…

数据结构与算法—数组栈和链表栈

数据结构与算法—数组栈和链表栈 &#x1f308;一览众山小数据结构与算法—数组栈和链表栈栈介绍栈图解栈实现数组实现栈实现思路实现代码单链表实现栈实现思路(图解)实现代码栈总结栈力扣栈介绍 栈,存储货物或供旅客住宿的地方,可引申为仓库、中转站&#xff0c;所以引入到计算…