【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>