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 选项。
运行项目
向后台传请求
在实际场景中,当单击某本图书链接时,应该向服务器端发起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参数,表示当前导航正要离开的路由对象。
方法2: 导航守卫 beforeRouteUpdate
beforeRouteUpdate 守卫在当前路由改变、但是该组件被复用时调用。
删除刚才的$root对象的监听器,改用beforeRouteUpdate 守卫来实现
beforeRouteUpdate (to, from, next) { this.book = null; this.book = Books.find((item) => item.id == to.params.id); next(); }
注:next是一个函数对象,必须调用该函数才能解析钩子。