命名视图

想同时展示多个视图时,并且每个视图展示不同的组件时,可以使用命名视图。也就是 <router-view></router-view>
当想展示多个且不同的路由组件时可以设置 name 属性, name 属性默认值为 default

  1. <router-view name="default"></router-view><!-- 默认视图-->
  2. <router-view name="two"></router-view> <!-- 第二个视图-->
  3. <router-view name="three"></router-view><!-- 第三个视图-->

多个视图渲染不同的页面, 多个视图就需要多个组件,确保正确使用 components 配置 (带上 s):

  1. import Bar from './Bar'
  2. import Baz from './Baz'
  3. const router = new VueRouter({
  4. routes: [
  5. {
  6. path: '/',
  7. components: {
  8. default: Foo,
  9. two: Bar,
  10. three: Baz
  11. }
  12. }
  13. ]
  14. })

案例

当使用多个默认视图

app.vue的源码

  1. <template>
  2. <div id="app">
  3. <div class="nav-box">
  4. <div class="logo">zxt</div>
  5. <!-- <router-link to="/home" tag="div" class="logo" >ZXT</router-link> -->
  6. <div class="nav-list">
  7. <router-link to="/home">首页</router-link>
  8. <router-link to="/learn">课程学习</router-link>
  9. <router-link to="/show">学员展示</router-link>
  10. <router-link to="/about">关于</router-link>
  11. <router-link to="/community">社区</router-link>
  12. </div>
  13. </div>
  14. <div class="content">
  15. <!--多个视图-->
  16. <router-view></router-view>
  17. <router-view></router-view>
  18. </div>
  19. </div>
  20. </template>
  21. <script>
  22. export default {
  23. name: 'App',
  24. components: {
  25. },
  26. }
  27. </script>
  28. <style>
  29. :root,body{
  30. height: 100%;
  31. }
  32. #app {
  33. font-family: Avenir, Helvetica, Arial, sans-serif;
  34. -webkit-font-smoothing: antialiased;
  35. -moz-osx-font-smoothing: grayscale;
  36. text-align: center;
  37. }
  38. .nav-box{
  39. width: 100%;
  40. height: 60px;
  41. display: flex;
  42. justify-content: space-around;
  43. align-items: center;
  44. background: rgba(0, 0, 200, .5);
  45. }
  46. .logo{
  47. color: #fff;
  48. font-size: 30px;
  49. font-weight: bold;
  50. cursor: pointer;
  51. }
  52. .nav-list{
  53. display: flex;
  54. width: 60%;
  55. justify-content: space-between;
  56. align-items: center;
  57. }
  58. .nav-list a{
  59. text-decoration: none;
  60. color: #000;
  61. font-size: 18px;
  62. }
  63. /* 此处修改选中效果,不然当单击二级导航栏时,一级导航栏没有选中效果 */
  64. .nav-list a.router-link-active{
  65. font-weight: bold;
  66. color: #fff;
  67. }
  68. .content{
  69. margin-top: 40px;
  70. font-size: 20px;
  71. }
  72. </style>

route.vue的源码

  1. {
  2. path: '/show',
  3. component: () => import('./components/views/Show.vue')
  4. },

效果图
image.png

当多个视图各个展示的不一样

app.vue的代码

  1. <template>
  2. <div id="app">
  3. <div class="nav-box">
  4. <div class="logo">zxt</div>
  5. <!-- <router-link to="/home" tag="div" class="logo" >ZXT</router-link> -->
  6. <div class="nav-list">
  7. <router-link to="/home">首页</router-link>
  8. <router-link to="/learn">课程学习</router-link>
  9. <router-link to="/show">学员展示</router-link>
  10. <router-link to="/about">关于</router-link>
  11. <router-link to="/community">社区</router-link>
  12. </div>
  13. </div>
  14. <div class="content">
  15. <!--多个视图-->
  16. <router-view></router-view>
  17. <router-view name="view"></router-view>
  18. </div>
  19. </div>
  20. </template>
  21. <script>
  22. export default {
  23. name: 'App',
  24. components: {
  25. },
  26. }
  27. </script>
  28. <style>
  29. :root,body{
  30. height: 100%;
  31. }
  32. #app {
  33. font-family: Avenir, Helvetica, Arial, sans-serif;
  34. -webkit-font-smoothing: antialiased;
  35. -moz-osx-font-smoothing: grayscale;
  36. text-align: center;
  37. }
  38. .nav-box{
  39. width: 100%;
  40. height: 60px;
  41. display: flex;
  42. justify-content: space-around;
  43. align-items: center;
  44. background: rgba(0, 0, 200, .5);
  45. }
  46. .logo{
  47. color: #fff;
  48. font-size: 30px;
  49. font-weight: bold;
  50. cursor: pointer;
  51. }
  52. .nav-list{
  53. display: flex;
  54. width: 60%;
  55. justify-content: space-between;
  56. align-items: center;
  57. }
  58. .nav-list a{
  59. text-decoration: none;
  60. color: #000;
  61. font-size: 18px;
  62. }
  63. /* 此处修改选中效果,不然当单击二级导航栏时,一级导航栏没有选中效果 */
  64. .nav-list a.router-link-active{
  65. font-weight: bold;
  66. color: #fff;
  67. }
  68. .content{
  69. margin-top: 40px;
  70. font-size: 20px;
  71. }
  72. </style>

route.js 的源码

  1. {
  2. path: '/show',
  3. components:{
  4. default: () => import('./components/views/Show.vue'),
  5. view: () => import('./components/views/About.vue')
  6. }
  7. },

show.vue

  1. <template>
  2. <div class="show">学员展示</div>
  3. </template>

about.vue

  1. <template>
  2. <div class="about">关于</div>
  3. </template>

效果图
image.png

路由组件传参

以动态路由为例,你会发现question.vue 渲染页面的时候需要通过$route进行一系列操作,这就写死啦只能在当动态路由下才能使用。其他地方是无法使用的。当我们想把question.vue当做组件使用时,就会发现缺少参数
示例
动态路由匹配中的question的源码

  1. <template>
  2. <div v-if="data">
  3. <div class="title">
  4. {{ data.title }}
  5. </div>
  6. <div class="option" >
  7. <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>
  8. </div>
  9. </div>
  10. </template>
  11. <script>
  12. export default {
  13. data(){
  14. return {
  15. data:null
  16. }
  17. },
  18. computed:{
  19. /**
  20. * 计算属性
  21. * 下一篇文章与上一篇的文章
  22. */
  23. optionQusetinList(){
  24. let arr = []
  25. if(this.data.next){
  26. const {next,nextId} = this.data
  27. arr.push({
  28. type:'next',
  29. title:next,
  30. id:nextId,
  31. })
  32. }
  33. if(this.data.prev){
  34. const {prev ,prevId} = this.data
  35. arr.push({
  36. type:'prev',
  37. title:prev,
  38. id:prevId,
  39. })
  40. }
  41. return arr
  42. }
  43. },
  44. methods:{
  45. /**
  46. * 获取数据
  47. */
  48. getData(){
  49. const { id } = this.$route.params
  50. this.$axios.get(`/question/${id}`).then(res =>{
  51. this.data = res
  52. })
  53. },
  54. /**
  55. * 触发单击事件修改路由
  56. */
  57. handleClick(id){
  58. const { name } = this.$route
  59. this.$router.push({name,params:{id}})
  60. }
  61. },
  62. /**
  63. * 监听路由信息是否被修改
  64. * 当路由信息被修改后重新获取数据
  65. */
  66. watch:{
  67. '$route':{
  68. handler(){
  69. this.getData()
  70. },
  71. immediate: true
  72. }
  73. }
  74. }
  75. </script>
  76. <style scoped>
  77. .option{
  78. width: 80%;
  79. height: 30px;
  80. position: fixed;
  81. left: 0;
  82. right: 0;
  83. bottom: 10px;
  84. margin: 10px auto;
  85. }
  86. .option-item{
  87. width: 200px;
  88. white-space: nowrap;
  89. overflow: hidden;
  90. text-overflow: ellipsis;
  91. color: #3385ff;
  92. cursor: pointer;
  93. }
  94. .option-item:hover{
  95. color: red;
  96. }
  97. .option-item.next{
  98. float: right;
  99. }
  100. .option-item .right{
  101. float: left;
  102. }
  103. </style>

在课程学习页面(课程学习页面的源码文件为learn.vue)吧question当做组件引入

  1. <template>
  2. <div class="learn">
  3. 课程学习
  4. <router-question></router-question>
  5. </div>
  6. </template>
  7. <script>
  8. import routerQuestion from "./question"
  9. export default {
  10. components:{
  11. routerQuestion
  12. }
  13. }
  14. </script>

效果图
image.png
你会发现报错信息是找不到,因为question.vue中你获取页面数据的id值是从动态路由的参数中获取到的

  1. const { id } = this.$route.params

路由名字也是

  1. const { name } = this.$route

你在看当前页面的路由
image.png
而动态路由为
image.png
那吗我们可以将所需要的数据传递进去

使用prop来传递参数

learn.vue中的代码修改为

  1. <template>
  2. <div class="learn">
  3. 课程学习
  4. <router-question :id='90878976' name="question" ></router-question>
  5. </div>
  6. </template>
  7. <script>
  8. import routerQuestion from "./question"
  9. export default {
  10. components:{
  11. routerQuestion
  12. }
  13. }
  14. </script>

修改question .vue 的源码

  1. <template>
  2. <div v-if="data">
  3. <div class="title">
  4. {{ data.title }}
  5. </div>
  6. <div class="option" >
  7. <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>
  8. </div>
  9. </div>
  10. </template>
  11. <script>
  12. export default {
  13. // 接受传递过来的参数
  14. props:{
  15. id:{
  16. type:[String,Number],
  17. },
  18. name:{
  19. type:String,
  20. }
  21. },
  22. data(){
  23. return {
  24. data:null
  25. }
  26. },
  27. mounted(){
  28. console.log(this.id)
  29. console.log(this.name)
  30. },
  31. computed:{
  32. /**
  33. * 计算属性
  34. * 下一篇文章与上一篇的文章
  35. */
  36. optionQusetinList(){
  37. let arr = []
  38. if(this.data.next){
  39. const {next,nextId} = this.data
  40. arr.push({
  41. type:'next',
  42. title:next,
  43. id:nextId,
  44. })
  45. }
  46. if(this.data.prev){
  47. const {prev ,prevId} = this.data
  48. arr.push({
  49. type:'prev',
  50. title:prev,
  51. id:prevId,
  52. })
  53. }
  54. return arr
  55. }
  56. },
  57. methods:{
  58. /**
  59. * 获取数据
  60. */
  61. getData(){
  62. const { id } = this
  63. this.$axios.get(`/question/${id}`).then(res =>{
  64. this.data = res
  65. })
  66. },
  67. /**
  68. * 触发单击事件修改路由
  69. */
  70. handleClick(id){
  71. const { name } = this
  72. console.log(name)
  73. this.$router.push({name,params:{id}})
  74. }
  75. },
  76. /**
  77. * 监听路由信息是否被修改
  78. * 当路由信息被修改后重新获取数据
  79. */
  80. watch:{
  81. '$route':{
  82. handler(){
  83. this.getData()
  84. },
  85. immediate: true
  86. }
  87. }
  88. }
  89. </script>
  90. <style scoped>
  91. .option{
  92. width: 80%;
  93. height: 30px;
  94. position: fixed;
  95. left: 0;
  96. right: 0;
  97. bottom: 10px;
  98. margin: 10px auto;
  99. }
  100. .option-item{
  101. width: 200px;
  102. white-space: nowrap;
  103. overflow: hidden;
  104. text-overflow: ellipsis;
  105. color: #3385ff;
  106. cursor: pointer;
  107. }
  108. .option-item:hover{
  109. color: red;
  110. }
  111. .option-item.next{
  112. float: right;
  113. }
  114. .option-item .right{
  115. float: left;
  116. }
  117. </style>

router.js

  1. {
  2. /**
  3. * 动态路由匹配
  4. * /question/下的参数都将是question.vue 渲染出来的
  5. */
  6. path:'/question/:id',
  7. name:'question',
  8. props:true, // 开启路由组件传递参数
  9. component:() => import('./components/views/question.vue')
  10. }

router.js 中使用的模式 一共有三种模式

模式

布尔模式

如果 props 被设置为 true,route.params 将会被设置为组件属性。
上面的router.js就是使用的布尔模式

对象模式

如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用

  1. {
  2. /**
  3. * 动态路由匹配
  4. * /question/下的参数都将是question.vue 渲染出来的
  5. */
  6. path:'/question/:id',
  7. name:'question',
  8. props:{
  9. id: 67809854,
  10. },
  11. component:() => import('./components/views/question.vue')
  12. }

函数模式

你可以创建一个函数返回 props。函数的第一个参数是 route (即$route)。

  1. {
  2. /**
  3. * 动态路由匹配
  4. * /question/下的参数都将是question.vue 渲染出来的
  5. */
  6. path:'/question/:id',
  7. name:'question',
  8. // 函数模式
  9. props:route =>({
  10. name:route.name,
  11. id: route.params.id,
  12. }),
  13. component:() => import('./components/views/question.vue')
  14. }