1.4 嵌套路由(尚未解决)
1.4.1 概述
在实际应用场景中,一个界面 UI 通常由多层嵌套的组件组合而成, URL 中的各段也按某种结构对应嵌套的各层组件,比如每个用户页面下面都有 profile 和 posts 两个子组页面,路径 /user/:id 映射到对应的 User 组件,根据 ID 的不同显示不同的用户信息,ID 为 1 的用户点击 user/1/profile ,将在用户 1 的视图中渲染 profile 组件,点击 user/1/posts ,将在用户 1 的视图中渲染 posts 组件。
1.4.2 改造 Book.vue 组件(尚未解决)
第一步:创建 books.js 文件
用于模拟从后端请求到的图书的数据,真实场景中使用 Ajax 从后端请求数据
export default [
{ id: 1, title: 'Java 无难事', desc: '让你的 Java 学习再无难事!' },
{ id: 2, title: 'VC++ 深入理解', desc: '畅销 10 多年的图书!' },
{ id: 3, title: 'Servlet/JSP 深入理解', desc: '经典 JSP 图书!' }
]
第二步:修改 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>
<!-- 路由视图 -->
<router-view />
</div>
</template>
<script>
// 导入数据
import books from '@/assets/js/books.js'
export default {
setup () {
return { books }
}
}
</script>
<style>
</style>
第三步:创建 Book.vue 组件
用户展示图书的具体信息
<template>
<div>
<p>图书id:{{ book.id }}</p>
<p>书名:{{ book.title }}</p>
<p>说明:{{ book.desc }}</p>
</div>
</template>
<script>
// 导入数据
import books from '@/assets/js/books.js'
// 导入路由
import { useRoute } from 'vue-router'
// 导入监听器
import { watch } from 'vue'
export default {
setup () {
// 拿到路由
const route = useRoute()
// 从 books 中找到当前 id 的图书信息
let book = books.find(item => item.id === route.params.id)
// 监听参数中 id 的变化,更新图书信息
watch(() => route.params.id, currentValue => {
console.log(currentValue)
book = books.find(item => item.id === currentValue)
})
return { books, book }
}
}
</script>
<style>
</style>
第四步:修改 index.js 文件
import { createRouter, createWebHashHistory } from 'vue-router'
import Study from '../views/Study.vue'
import Home from '../views/Home.vue'
import News from '../views/News.vue'
import Books from '../views/Books.vue'
import Videos from '../views/Videos.vue'
import Book from '../views/Book.vue'
const routes = [
{
path: '/',
component: Study,
redirect: '/home',
children: [
{
path: '/home',
component: Home
}, {
path: '/news',
component: News
}, {
// 本来我们就使用嵌套路由了,咋这里我们再次向下嵌套
path: '/books',
component: Books,
children: [
{ path: '/books/:id', component: Book }
]
}, {
path: '/videos',
component: Videos
}
]
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
第五步:修改 Study.vue
<template>
<router-link to="/">主页</router-link>
<router-link to="/news">新闻</router-link>
<router-link to="/books">图书</router-link>
<router-link to="/videos">视频</router-link>
<div>=================</div>
<router-view />
</template>
<script>
export default {
el: 'Study'
}
</script>
<style>
</style>
第六步:运行结果,踩坑
这么写
book = books.find(item => item.id === route.params.id)
找不到对应的图书数据,但是这么写book = books.find(item => item.id === 1)
可以找到,离谱的是console.log(route.params.id)
的输出结果是 1 ,也就是说使用真实的数字它就能找到,使用变量代替数字它就找不到!离谱!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1cmglvr8-1641036386276)(image-20210622102742667.png)]
将参数改成 1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-76skqpCq-1641036386277)(image-20210622102930390.png)]
第七步:问题代码记录
<template>
<div>
<p>图书id:{{ book }}</p>
<p>书名:{{ book }}</p>
<p>说明:{{ book }}</p>
</div>
</template>
<script>
// 导入数据
import books from '@/assets/js/books.js'
// 导入路由
import { useRoute } from 'vue-router'
// 导入监听器
import { watch, reactive } from 'vue'
export default {
setup () {
// 拿到路由
const route = useRoute()
// 从 books 中找到当前 id 的图书信息
let book = reactive({})
console.log('打印route.params.id: ' + route.params.id)
console.log('find 中使用 route.params.id')
book = books.find(item => item.id === route.params.id)
console.log('查找图书结果:' + book)
// 监听参数中 id 的变化,更新图书信息
watch(() => route.params.id, currentValue => {
console.log('当前值:' + currentValue)
book = books.find(item => item.id === currentValue)
})
return { books, book }
}
}
</script>
<style>
</style>