Vue从入门到实战:嵌套路由

来自CloudWiki
跳转至: 导航搜索

嵌套路由的定义

在实际的应用场景中,一个界面UI通常由多层嵌套的组件组合而成,URL中的各段也按某种结构对应嵌套的各层组件

如 user/1/profile表示 ,在用户1的视图中渲染Profile组件

前置知识:Vue从入门到实战:感受前端路由

从后台传数据

继续Vue从入门到实战:感受前端路由中的例子,

当单击“图书”链接时,以列表形式显示所有图书的书名,进一步单击单个书名链接,在Books视图中显示图书的详细信息。


后台数据

在assets目录中新建一个books.js文件,里面是图书数据

export default [
   {id: 1, title: 'Vue.js无难事', desc: '前端框架经典图书'},
   {id: 2, title: 'VC++深入详解', desc: '畅销10多年的图书'},
   {id: 3, title: 'Servlet/JSP深入详解', desc: '经典JSP图书'}
]

此处模拟了后台服务器传来的数据。

App.vue

<template>
  <div id="app">
    <p>
    
      <router-link to="/news">新闻</router-link>
      <router-link to="/books">图书</router-link>
      <router-link to="/videos">视频</router-link>

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

<script>
export default {
  name: 'app',
  components: {
  }
}
</script>


components

修改Books.vue ,以列表形式展示图书数据。

<template>
    <div>
        <h3>图书列表</h3>
        <ul>
            <li v-for="book in books" :key="book.id">
                
                <router-link :to="'/book/' + book.id">{{book.title}}</router-link>
              

            </li>
        </ul>
        <!--Book组件在这里渲染-->
        
        <router-view></router-view>
        
    </div>
</template>

<script>
// 导入Books数组
import Books from '@/assets/books'
export default {
    data(){
        return {
            books: Books
        }
    },

}
</script>

所用到的Book组件:

Book.vue:

<template>
	<div>
		图书ID: {{ $route.params.id }}
	</div>
</template>

<script>
</script>

<style>
</style>


router目录

import Vue from 'vue'
import VueRouter from 'vue-router'  // 导入vue-router
import News from '@/components/News'
import Books from '@/components/Books'
import Videos from '@/components/Videos'
import Book from '@/components/Book'

Vue.use(VueRouter)  //安装vue-router插件

// 将VueRouter实例作为模块的默认导出
const router = new VueRouter({

  routes: [
    {
      path: '/news',
      component:News
    },
    
    {
      path: '/videos',
      component:Videos
    },

    {
      path: '/books',
      component: Books,
      children:[
	{path: '/book/:id', component:Book}
      ]
    },
		
		
  ]
})

export default router;

要在嵌套的出口(Books组件中的<router-view>)中渲染组件,

需要在routers选项的配置中使用children 选项。

运行项目

Vue21022402.png

向后台传请求

在实际场景中,当单击某本图书链接时,应该向服务器端发起Ajax请求来获取图书详细数据,于是我们想:通过什么函数来触发、向后台传递参数。

比方说,从book/1导航到book/2时,怎么向后台发送请求。

方法1:监听$route对象

要对同一组件中的路由参数更改做出响应,只需监听$route对象。

<template>
	<div>
		<p>图书ID:{{ book.id }}</p>
		<p>书名:{{ book.title }}</p>
		<p>说明:{{ book.desc }}</p>
	</div>
</template>

<script>
import Books from '@/assets/books'
export default {
    data(){
        return {
            book: {}
        }
    },
    methods: {
        setBook(book){
            this.book = book;
        }
    },
//     created(){
//         this.book = Books.find((item) => item.id == this.$route.params.id);
//     },
//     
//     
//     watch: {
//         '$route' (to) {
//             this.book = Books.find((item) => item.id == to.params.id);
//         }
//     } 
    watch: {
        '$route': {
            handler: function(to) {
                this.book = Books.find((item) => item.id == to.params.id);
            },
            immediate: true
        } 
    } 

}
</script>

<style>
	
</style>

当路由参数发生变化时,$route对象的监听器被调用。

$route对象的监听器函数的to参数表示即将进入的目标路由对象,该函数还可以带一个from参数,表示当前导航正要离开的路由对象。

Vue21022403.png

方法2: 导航守卫 beforeRouteUpdate

beforeRouteUpdate 守卫在当前路由改变、但是该组件被复用时调用。

删除刚才的$root对象的监听器,改用beforeRouteUpdate 守卫来实现

      
beforeRouteUpdate (to, from, next) {
           this.book = null;      
           this.book = Books.find((item) => item.id == to.params.id);
           next();
       }

注:next是一个函数对象,必须调用该函数才能解析钩子。

Vue21022403.png