效果分析
- 功能分析
- 通过演示效果发现,主要的功能页面有两个,一个是列表页,一个是详情页,并且在列表页点击时可以跳转到详情页
- 底部导航可以来回切换,并且切换时,只有上面的主题内容在动态渲染
分析:配路由 + 实现功能
1.配置路由
- 首页和面经详情页,两个一级路由
- 首页内嵌套4个可切换的页面(嵌套二级路由)
2.实现功能
- 首页请求渲染
- 跳转传参 到 详情页,详情页动态渲染
- 组件缓存,性能优化
路由配置
一级路由配置
1.把文档中准备的素材拷贝到项目中
2.针对router/index.js文件 进行一级路由配置
index.js
...
import Layout from '@/views/Layout.vue'
import ArticleDetail from '@/views/ArticleDetail.vue'
...
const router = new VueRouter({
routes: [
{
path: '/',
component: Layout
},
{
path: '/detail',
component: ArticleDetail
}
]
})
二级路由配置
1.使用场景
当在页面中点击链接跳转,只是部分内容切换时,我们可以使用嵌套路由
2.语法
- 在一级路由下,配置children属性即可
- 配置二级路由的出口
在一级路由下,配置children属性
注意 : 一级的路由path 需要加 / 二级路由的path不需要加 /
const router = new VueRouter({
routes: [
{
path: '/',
component: Layout,
children:[
//children中的配置项 跟一级路由中的配置项一模一样
{path:'xxxx',component:xxxx.vue},
{path:'xxxx',component:xxxx.vue},
]
}
]
})
技巧:二级路由应该配置到哪个一级路由下呢?
这些二级路由对应的组件渲染到哪个一级路由下,children就配置到哪个路由下边
2.配置二级路由的出口
注意: 配置了嵌套路由,一定配置对应的路由出口,否则不会渲染出对应的组件 Layout.vue
router/index.js
...
import Article from '@/views/Article.vue'
import Collect from '@/views/Collect.vue'
import Like from '@/views/Like.vue'
import User from '@/views/User.vue'
...
const router = new VueRouter({
routes: [
{
path: '/',
component: Layout,
redirect: '/article',
children:[
{
path:'/article',
component:Article
},
{
path:'/collect',
component:Collect
},
{
path:'/like',
component:Like
},
{
path:'/user',
component:User
}
]
},
....
]
})
Layout.vue
<template>
<div class="h5-wrapper">
<div class="content">
<!-- 内容部分 -->
<router-view></router-view>
</div>
<nav class="tabbar">
<a href="#/article">面经</a>
<a href="#/collect">收藏</a>
<a href="#/like">喜欢</a>
<a href="#/user">我的</a>
</nav>
</div>
</template>
导航高亮
1.实现思路
- 将a标签替换成 组件,配置to属性,不用加 #
- 结合高亮类名实现高亮效果 (推荐模糊匹配:router-link-active)
Layout.vue
....
<nav class="tabbar">
<router-link to="/article">面经</router-link>
<router-link to="/collect">收藏</router-link>
<router-link to="/like">喜欢</router-link>
<router-link to="/user">我的</router-link>
</nav>
<style>
a.router-link-active {
color: orange;
}
</style>
页面请求渲染
步骤如下:
1.安装axios
yarn add axios npm i axios
2.接口文档
请求地址: https://mock.boxuegu.com/mock/3083/articles
请求方式: get
3.created中发送请求,获取数据,存储到data中
Article.vue
data() {
return {
articelList: [],
}
},
async created() {
const { data: { result: { rows } }} = await axios.get('https://mock.boxuegu.com/mock/3083/articles')
this.articelList = rows
},
页面动态渲染
<template>
<div class="article-page">
<div class="article-item" v-for="item in articelList" :key="item.id">
<div class="head">
<img :src="item.creatorAvatar" alt="" />
<div class="con">
<p class="title">{{ item.stem }}</p>
<p class="other">{{ item.creatorName }} | {{ item.createdAt }}</p>
</div>
</div>
<div class="body">
{{item.content}}
</div>
<div class="foot">点赞 {{item.likeCount}} | 浏览 {{item.views}}</div>
</div>
</div>
</template>
跳转传参:
查询参数传参(更适合多个参数)
?参数名=参数值 =>this.$rout.query
Article.vue
<template>
<div class="article-page">
<div class="article-item"
v-for="item in articelList" :key="item.id"
@click="$router.push(`/detail?id=${item.id}`)">
...
</div>
</div>
</template>
ArticleDetail.vue
created(){
console.log(this.$route.query.id)
}
动态路由传参(单个参数更方便)
=>改造路由=>/路径/参数 =>this.$router.params.参数名
router/index.js
...
{
path: '/detail/:id',
component: ArticleDetail
}
Article.vue
<div class="article-item"
v-for="item in articelList" :key="item.id"
@click="$router.push(`/detail/${item.id}`)">
....
</div>
ArticleDetail.vue
created(){
console.log(this.$route.params.id)
}
额外优化功能点-点击回退跳转到上一页($router.back)
ArticleDetail.vue
<template>
<div class="article-detail-page">
<nav class="nav"><span class="back" @click="$router.back()"><</span> 面经详情</nav>
....
</div>
</template>
详情页渲染
1.实现步骤分析
- 导入axios
- 查看接口文档
- 在created中发送请求
- 页面动态渲染
ArticleDetail.vue
<template>
<div class="article-detail-page">
<nav class="nav">
<span class="back" @click="$router.back()"><</span> 面经详情
</nav>
<header class="header">
<h1>{{articleDetail.stem}}</h1>
<p>{{articleDetail.createAt}} | {{articleDetail.views}} 浏览量 | {{articleDetail.likeCount}} 点赞数</p>
<p>
<img
:src="articleDetail.creatorAvatar"
alt=""
/>
<span>{{articleDetail.creatorName}}</span>
</p>
</header>
<main class="body">
{{articleDetail.content}}
</main>
</div>
</template>
组件缓存 keep-alive
定义:
-
keep-alive 是 Vue 的内置组件,当它包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
-
keep-alive 是一个抽象组件:它自身不会渲染成一个 DOM 元素,也不会出现在父组件中。
优点:
-
在组件切换过程中把切换出去的组件保留在内存中,防止重复渲染DOM,
-
减少加载时间及性能消耗,提高用户体验性。
App.vue
<template>
<div class="h5-wrapper">
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>
</template>
问题:缓存了所有被切换的组件
包裹在keep-alive 二级路由匹配的组件都会被Layout组件 Detail组件都会被缓存
三个属性
① include : 组件名数组,只有匹配的组件会被缓存
② exclude : 组件名数组,任何匹配的组件都不会被缓存
③ max : 最多可以缓存多少组件实例
- include与exclude一般不会同时使用
- exclude一般配合max使用
App.vue
<template>
<div class="h5-wrapper">
<keep-alive :include="['LayoutPage']">
<router-view></router-view>
</keep-alive>
</div>
</template>
如果没有配置name,才会找文件名为组件名,name优先级更高
默认情况 name作为组件名
额外的两个生命周期钩子
keep-alive的使用会触发两个生命周期函数
-
activated 当组件被激活(使用)的时候触发 → 进入这个页面的时候触发
-
deactivated 当组件不被使用的时候触发 → 离开这个页面的时候触发
组件被激活就不会执行组件的created, mounted, destroyed 等钩子了
所以其提供了actived 和deactived钩子,帮我们实现业务需求。
总结: