【Vue.js学习笔记】20:使用vue-router做动态路由,嵌套路由

学习b站上的小马视频。

动态路由

动态路由可以设置动态参数等,适合REST风格的接口,或者用于url级别的分页等功能。

App.vue

这里设置一个类似导航条或者分页条的路由。

<template>
  <div id="app">
    <!--在这里设置去不同页面的路由-->
    <p>
      <router-link to="/">主页</router-link>
      <router-link to="/player/1">第一页</router-link>
      <router-link to="/player/2">第二页</router-link>
    </p>

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

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

<style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>

router/index.js

在这里配置组件的路由映射。

import Vue from 'vue'
import Router from 'vue-router'

//导入要映射到的组件们
import Hello from '../page/xiaoma/Hello'
import Player from '../page/xiaoma/Player'

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/',//主页,显然这是一个静态路由
      name: 'Hello',
      component: Hello
    },
    {
      path: '/Player/:uid',//这是一个带参数uid的动态路由
      name: 'Player',
      component: Player
    }
  ]
})

Player.vue

使用了动态路由的组件,在钩子函数中根据路由参数来请求指定的资源。

<template>
  <div>
    <h5>这里是第{{page}}页</h5>
    <p>我是{{detail.name}},我的年龄是{{detail.age}}</p>
  </div>
</template>

<script> export default { name: "Player", data() { return { page: 0, detail: {} } }, //组件加载一次之后就不会再加载了(第x页->第x页),所以不应该写在mounted里 //但是这部分也不能去掉,否则组件第一次加载时没法获取到数据(主页->第x页) mounted() { //在这里获取动态路由的参数 this.page = this.$route.params.uid; //然后通过这个参数请求到内容 this.detail = this.getDetail(this.page); }, //而是写在下面这个方法中,这样每次路由发生更新前都会调用这个方法 beforeRouteUpdate(to, from, next) { //在这里获取动态路由的参数(注意这里从第一个参数中获取) this.page = to.params.uid; //然后通过这个参数请求到内容 this.detail = this.getDetail(this.page); //这里next()不传参会正常执行管道中的下一个钩子 next(); }, methods: { getDetail(i) { //这里应该向服务器请求对应的资源,这里直接简单的模拟成switch返回 switch (i.toString()) { case '1': return {uid: 1, name: "唐僧", age: 25}; case '2': return {uid: 2, name: "孙悟空", age: 19}; default: return {uid: -1}; } } } } </script>

<style scoped> </style>

运行结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

嵌套路由

嵌套路由往往在前面的动态路由的基础上,如uid为某个值的用户的某些资源的访问(如简介、状态等)。

这个例子里App.vue和上面的一样。

router/index.js

在前面的基础上,为这个组件的路由配置子路由,映射到相应的组件上去。

import Vue from 'vue'
import Router from 'vue-router'

//导入要映射到的组件们
import Hello from '../page/xiaoma/Hello'
import Player from '../page/xiaoma/Player'
import Profile from '../page/xiaoma/Player/Profile'
import Status from '../page/xiaoma/Player/Status'

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/',//主页,显然这是一个静态路由
      name: 'Hello',
      component: Hello
    },
    {
      path: '/Player/:uid',//这是一个带参数uid的动态路由
      name: 'Player',
      component: Player,
      //设置其子路由,形成嵌套路由
      children: [
        {path: 'profile', component: Profile},
        {path: 'status', component: Status}
      ]
    }
  ]
})

Profile.vue

/player/:uid的子路由/player/:uid/profile对应的组件,这里是用户的简介页。这里都不再去写请求的部分,实际上应该去发送请求返回一些详细数据。

<template>
  <div>
    <h3>简介页面:我是{{$route.params.uid}}号</h3>
  </div>
</template>

<script> export default { name: "Profile" } </script>

<style scoped> </style>

Status.vue

/player/:uid的子路由/player/:uid/status对应的组件,这里是用户的状态页。

<template>
  <div>
    <h3>状态页面:{{$route.params.uid}}在线</h3>
  </div>
</template>

<script> export default { name: "Status" } </script>

<style scoped> </style>

Player.vue

注意,因为在这个组件的路由上嵌套了子路由,那就要在这个组件上设置子组件视图(<router-view/>标签)以形成动态的子组件关系。

<template>
  <div>
    <h5>这里是第{{page}}页</h5>
    <p>我是{{detail.name}},我的年龄是{{detail.age}}</p>
    <router-link v-bind:to="profileURL">去简介页</router-link>
    <router-link v-bind:to="statusURL">去状态页</router-link>
    <hr>
    <!--这里再嵌套一个router-view以展示这个组件的子组件-->
    <router-view></router-view>
  </div>
</template>

<script> export default { name: "Player", data() { return { page: 0, detail: {}, //添加简介页和状态页的URL,这里是变量(因为是动态页面,这个组件是复用的) profileURL: "", statusURL: "" } }, mounted() { this.page = this.$route.params.uid; this.detail = this.getDetail(this.page); //动态URL的确定 this.profileURL = "/player/" + this.page + "/profile"; this.statusURL = "/player/" + this.page + "/status"; }, beforeRouteUpdate(to, from, next) { this.page = to.params.uid; this.detail = this.getDetail(this.page); //动态URL的确定 this.profileURL = "/player/" + this.page + "/profile"; this.statusURL = "/player/" + this.page + "/status"; next(); }, methods: { getDetail(i) { //这里应该向服务器请求对应的资源,这里直接简单的模拟成switch返回 switch (i.toString()) { case '1': return {uid: 1, name: "唐僧", age: 25}; case '2': return {uid: 2, name: "孙悟空", age: 19}; default: return {uid: -1}; } } } } </script>

<style scoped> </style>

运行结果

在这里插入图片描述
在这里插入图片描述