何为动态路由匹配
当我们需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”来达到这个效果:
动态路由匹配效果
观察上图的URL你会发现当路径最后的数字修改时,页面会切换当时页面的都是用的一个模板,只是里面的数据更换啦
动态路由实例代码
const User = {
template: '<div>User</div>'
}
const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: '/user/:id', component: User }
]
})
{ path: '/user/:id', component: User }
经过这样设置/user/foo 与 /user/bar 都将映射到相同路由。也可说是公用啦一个模板
当路径参数使用冒号 :
标记。当匹配一个路由时(也就是URL) 动态路由的参数会被设置到到$route.params中
案例
效果图
源码router.rar
示例源码
配置源码
router.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import axios from './http'
Vue.prototype.$axios = axios;
// 使用路由
Vue.use(VueRouter)
Vue.config.productionTip = false
// 定义路由
const routes = [
{
path:'/',
// 当输入域名访问是,将其其路径重定向为/home
redirect:'/home'
},
{
path: '/home',
// 异步加载组件,当标签被点击才会加载组件
component: () => import('./components/views/Home.vue'),
// 别名
// 别名是 URL中的路径是“/home” 但路由匹配的则为“/”
// 但是如何是访问当用于只输入域名没有跟参数时回无效
// 建议使用重定向
// alias:'/'
},
{
path: '/learn',
component: () => import('./components/views/Learn.vue')
},
{
path: '/show',
component: () => import('./components/views/Show.vue')
},
{
path: '/about',
component: () => import('./components/views/About.vue')
},
{
path: '/community',
name:'community',
component: () => import('./components/views/community.vue'),
// 重定向
// 当单击社区时默认选中学术讨论
// 第一种
// redirect:'/community/academic',
// 第二种 通过命令路由
// redirect: { name:'academic'},
// 第三种 通过方法
redirect:to =>{
return {
name:'academic'
}
},
// 路由嵌套
children:[
{
path:'academic',
// 命名路由
name:'academic',
component:()=> import('./components/views/Academic.vue')
},
{
path:'personal',
name:'personal',
component: () => import('./components/views/Personal.vue')
},
{
path:'download',
name:'download',
component: () => import('./components/views/Download.vue')
},
]
},
{
/**
* 动态路由匹配
* /question/下的参数都将是question.vue 渲染出来的
*/
path:'/question/:id',
name:'question',
component:() => import('./components/views/question.vue')
}
]
// 创建实例
export default new VueRouter({
mode: 'history',
routes,
})
http.js
import axios from 'axios';
/**
* 设置默认请求地址
*/
axios.defaults.baseURL = 'http://localhost:8080/';
/**
* 请求拦截
*/
axios.interceptors.request.use(request => {
request.url += '.json'
return request;
})
/**
* 响应拦截
*/
axios.interceptors.response.use(response =>{
return response.data.data;
})
export default axios;
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
vue的代码
academic.vue — 学术讨论页面的源码
<template>
<div>
<ul class="quesiton-warp">
<router-link class="question-item" tag="li" v-for="question in data" :key="question.id" :to="{name:'question',params:{
id:question.id
}}">
{{ question.title}}
</router-link>
</ul>
</div>
</template>
<script>
export default {
data(){
return {
data:null,
}
},
methods:{
getData(){
this.$axios.get('/question').then(res =>{
console.log(res)
this.data = res;
})
}
},
mounted(){
this.getData()
}
}
</script>
<style scoped>
ul,li{
list-style: none;
}
li{
text-align: left;
line-height: 30px;
cursor: pointer;
}
li:hover{
color: #3385ff;
text-decoration: underline;
}
</style>
question.vue — 文章展示页面源码
<template>
<div v-if="data">
<div class="title">
{{ data.title }}
</div>
<div class="option" >
<div class="option-item" @click="handleClick(options.id)" v-for="options in optionQusetinList" :key="options.id" :title="options.title" :class="options.type"> {{ options.title}}</div>
</div>
</div>
</template>
<script>
export default {
data(){
return {
data:null
}
},
computed:{
/**
* 计算属性
* 下一篇文章与上一篇的文章
*/
optionQusetinList(){
let arr = []
if(this.data.next){
const {next,nextId} = this.data
arr.push({
type:'next',
title:next,
id:nextId,
})
}
if(this.data.prev){
const {prev ,prevId} = this.data
arr.push({
type:'prev',
title:prev,
id:prevId,
})
}
return arr
}
},
methods:{
/**
* 获取数据
*/
getData(){
const { id } = this.$route.params
this.$axios.get(`/question/${id}`).then(res =>{
this.data = res
})
},
/**
* 触发单击事件修改路由
*/
handleClick(id){
const { name } = this.$route
this.$router.push({name,params:{id}})
}
},
/**
* 监听路由信息是否被修改
* 当路由信息被修改后重新获取数据
*/
watch:{
'$route':{
handler(){
this.getData()
},
immediate: true
}
}
}
</script>
<style scoped>
.option{
width: 80%;
height: 30px;
position: fixed;
left: 0;
right: 0;
bottom: 10px;
margin: 10px auto;
}
.option-item{
width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #3385ff;
cursor: pointer;
}
.option-item:hover{
color: red;
}
.option-item.next{
float: right;
}
.option-item .right{
float: left;
}
</style>