您现在的位置是:首页 > 技术教程 正文

vue3使用vue-router嵌套路由(多级路由)

admin 阅读: 2024-04-01
后台-插件-广告管理-内容页头部广告(手机)

Vue3 嵌套路由的使用和 Vue2 相差不大,主要的区别是 Vue3 的路由实例化使用了 createApp() 方法,所以实例化路由时需要传入根组件。另外,Vue3 的路由对象除了包含 Vue2 中的导航守卫、导航钩子和解析守卫等功能外,还新增了 meta prop 和 route prop。

在使用嵌套路由时,建议将路由按照功能模块进行分层,每一层代表一个主要的功能块,每个层级下的路由数量不要过多,一般建议不要超过 10 个,层级也不要超过 5 层。同时,根据实际业务需求,可以适当调整路由层级和数量,以达到更好的管理和使用效果。

route文件下 index.ts文件代码:

  1. import {
  2. createRouter,
  3. createWebHashHistory,
  4. RouteRecordRaw
  5. } from "vue-router";
  6. // createWebHashHistory,createWebHistory
  7. const routes: RouteRecordRaw[] = [
  8. {
  9. path: '/',
  10. redirect: '/home',
  11. },
  12. {
  13. path: '/home',
  14. name: 'Home',
  15. component: () => import('@/views/Home/index.vue'),
  16. meta: {
  17. title: 'Home Page',
  18. roles: ['admin', 'admin1']
  19. },
  20. children: [
  21. {
  22. path: 'lx',
  23. name: 'Lx',
  24. component: () => import('@/views/Home/Lx.vue'),
  25. // 也可以使用props传参方式接收传来的参数
  26. props: (propsRouter) => {
  27. // console.log('props >router', propsRouter)
  28. // 可以return query 也可以return params支持两种传参方式
  29. return propsRouter.query
  30. },
  31. // 多级嵌套 建议用query传参
  32. children: [
  33. {
  34. path: 'childA',
  35. name: 'ChildA',
  36. component: () => import('@/views/Home/ChildA.vue'),
  37. },
  38. ]
  39. },
  40. {
  41. path: 'lxb/:id/:title', // 提前定义params参数(可以定义多个)
  42. name: 'Lxb',
  43. component: () => import('@/views/Home/Lxb.vue'),
  44. },
  45. ]
  46. },
  47. ]
  48. export const router = createRouter({
  49. // 路由的history模式,共有三种模式,
  50. // createWebHistory、createWebHashHistory、createMemoryHistory
  51. history: createWebHashHistory(),// history: createWebHistory(),
  52. // 路由配置
  53. routes,
  54. // 是否严格匹配路由
  55. strict: true,
  56. // 路由跳转完成后,页面滚动行为
  57. scrollBehavior: () => ({ left: 0, top: 0 }),
  58. })

main.ts文件代码:

  1. import { router } from './route/index'
  2. import { createApp } from 'vue'
  3. const app = createApp(App)
  4. app.use(router).mount('#app')

App.vue文件代码:

  1. <template>
  2. <router-view />
  3. </template>
  4. <script>
  5. import { defineComponent } from 'vue'
  6. // vue3.0版本语法
  7. export default defineComponent({
  8. name: 'App',
  9. })
  10. </script>

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

  1. <template>
  2. <div class="home">
  3. <h2>首页{{ title }}</h2>
  4. <!-- 模拟有权限时显示 -->
  5. <div v-if="roles.includes(role)">
  6. <h2>嵌套路由</h2>
  7. <router-link to="/home/lx">push跳转到/home/lx页面</router-link>
  8. <br>
  9. <!-- 加了/就要写全 /home/lxb -->
  10. <router-link replace to="/home/lxb/id:2/title:102">push跳转到/home/lxb页面</router-link>
  11. <router-view></router-view>
  12. </div>
  13. </div>
  14. </template>
  15. <script lang="ts">
  16. import { defineComponent, reactive, onMounted, toRefs, } from 'vue'
  17. import { useRoute, useRouter } from 'vue-router'
  18. export default defineComponent({
  19. name: 'Home',
  20. setup() {
  21. const router = useRouter()
  22. const route: any = useRoute()
  23. const state = reactive({
  24. title: '',
  25. role: '', // 我的当前角色
  26. roles: [''],
  27. routerGo: (path) => {
  28. if (path === 'lx') {
  29. // query传参可以用path 也可以用name: Lx
  30. router.push({
  31. path: path,
  32. query: {
  33. title: '101',
  34. id: 1
  35. }
  36. })
  37. // router.replace
  38. } else {
  39. // params传参只能用name
  40. router.replace({
  41. // path: path + '/id:2/title:102',
  42. name: 'Lxb',
  43. params: {
  44. title: '102',
  45. id: 2
  46. }
  47. })
  48. }
  49. },
  50. })
  51. onMounted(() => {
  52. console.log('/home', route)
  53. state.title = route.meta.title
  54. state.roles = route.meta.roles
  55. // 模拟一个接口
  56. setTimeout(() => {
  57. const res = {
  58. code: 200,
  59. data: {
  60. token: '123456',
  61. userName: '吴彦祖',
  62. role: 'admin'
  63. }
  64. }
  65. state.role = res.data.role
  66. }, 0)
  67. })
  68. return {
  69. ...toRefs(state)
  70. }
  71. }
  72. })
  73. </script>
  74. <style lang="less" scoped>
  75. .home {
  76. color: pink;
  77. font-size: 14px;
  78. }
  79. </style>

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

  1. <template>
  2. <div style="font-size: 14px;">
  3. <h2>我是练习b{{ route?.params?.title }}页面</h2>
  4. <div>id:{{ route?.params?.id }}</div>
  5. <button @click="routerGoBack">返回首页</button>
  6. </div>
  7. </template>
  8. <script lang="ts">
  9. import { defineComponent, onMounted, reactive, toRefs } from 'vue'
  10. import { useRoute, useRouter } from 'vue-router'
  11. // vue3.0语法
  12. export default defineComponent({
  13. name: 'Lxb',
  14. setup() {
  15. const route = useRoute()
  16. const router = useRouter()
  17. const state: any = reactive({
  18. routerGoBack: () => {
  19. router.replace('/home')
  20. //replace跳转进来的不可以使用router.go(-1) 路由栈是空的》回不到上一个路由
  21. },
  22. })
  23. onMounted(() => {
  24. console.log(route)
  25. })
  26. return {
  27. route,
  28. ...toRefs(state)
  29. }
  30. },
  31. })
  32. </script>

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

  1. <template>
  2. <div style="font-size: 14px;">
  3. <h2>我是练习{{ title }}页面</h2>
  4. <div>id:{{ id }}</div>
  5. <div>props: {{ props }}</div>
  6. <button @click="routerGoBack">返回上一页</button>
  7. <br>
  8. <button @click="routerGo('/home/lx/childA')">去子路由childA</button>
  9. <!-- <router-view></router-view> -->
  10. <router-view />
  11. </div>
  12. </template>
  13. <script lang="ts">
  14. import { defineComponent, onMounted, reactive, toRefs } from 'vue'
  15. import { useRoute, useRouter } from 'vue-router'
  16. // vue3.0语法
  17. export default defineComponent({
  18. name: 'Lx',
  19. props: {
  20. id: {
  21. type: String,
  22. default: ''
  23. },
  24. title: {
  25. type: String,
  26. default: ''
  27. },
  28. },
  29. setup(props) {
  30. const route = useRoute()
  31. const router = useRouter()
  32. const state: any = reactive({
  33. id: '',
  34. title: '',
  35. routerGoBack: () => {
  36. router.go(-1) // go(-1)回到上一个路由
  37. // 也可以用router.replace('/home')跳回指定页
  38. },
  39. routerGo: (path) => {
  40. router.push(path)
  41. }
  42. })
  43. onMounted(() => {
  44. console.log('lx route', route)
  45. console.log('lx props', props)
  46. if (route.query) {
  47. state.id = route.query.id
  48. state.title = route.query.title
  49. }
  50. })
  51. return {
  52. props,
  53. ...toRefs(state)
  54. }
  55. },
  56. })
  57. </script>

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

  1. <template>
  2. <div style="font-size: 14px;background: skyblue;">
  3. <h3>我是ChildA组件</h3>
  4. <h3>route.query:{{ route.query }}</h3>
  5. </div>
  6. </template>
  7. <script lang="ts">
  8. import { defineComponent, onMounted, } from 'vue'
  9. import { useRoute, useRouter } from 'vue-router'
  10. // vue3.0语法
  11. export default defineComponent({
  12. name: 'ChildA',
  13. setup() {
  14. const router = useRouter()
  15. const route = useRoute()
  16. function goBack() {
  17. router.go(-1)
  18. }
  19. onMounted(() => {
  20. console.log(route)
  21. })
  22. // 可以在页面销毁前清除事件
  23. // onUnmounted(() => {
  24. // proxy.$mittBus.off('mittUserA')
  25. // })
  26. return {
  27. route, goBack
  28. }
  29. },
  30. })
  31. </script>

初始页面效果:

先点击push跳转到/home/lxb页面>(嵌套一层的路由)页面效果:

嵌套一层的路由从原本/home跳入了/home/lxb 子路由页面,点击回到首页。

 

 再点击push跳转到/home/lx页面>(嵌套多层的路由)页面效果:

先去到了第一层/home/lx子路由页面,

再点击去子路由childA按钮>页面效果:

进到了嵌套的第二层/home/lx/childA子路由页面

点击可返回上一页/home/lx 再点击可回到/home首页。

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

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

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

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

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

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

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索
排行榜