何为动态路由匹配
当我们需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 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:'/',// 当输入域名访问是,将其其路径重定向为/homeredirect:'/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 = falsenew 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.dataarr.push({type:'next',title:next,id:nextId,})}if(this.data.prev){const {prev ,prevId} = this.dataarr.push({type:'prev',title:prev,id:prevId,})}return arr}},methods:{/*** 获取数据*/getData(){const { id } = this.$route.paramsthis.$axios.get(`/question/${id}`).then(res =>{this.data = res})},/*** 触发单击事件修改路由*/handleClick(id){const { name } = this.$routethis.$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>
