转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
涉及面试题:
keep-alive 标签的目的是什么?
[编号:travel_18]
1 问题分析
我们的项目开发到这里,“首页”和“城市选择页”好像都已经完成了,整个开发过程中也进行过多次代码的优化、性能的优化,看起来并没有什么问题。
但实际上,就整个网页性能上来说,它依然存在问题。
我们打开控制台的 Network,选中 XHR 查看请求。当在首页点击城市,切换到城市选择页后,会请求城市的数据 city.json ;从城市选择页跳转回首页时,又会请求一次首页的数据 index.json 。即,在首页与城市选择页间切换时,每次都会重新发送请求:
❓为什么会重复发送请求呢?
答:因为每次路由重新从城市选择页 /city 切换到首页 / 时,首页 Home.vue 就会被重新渲染,然后 mounted 这个生命周期函数就会重新执行,去发送请求、获取数据(首页切换至城市选择页同理)。
2 使用 <keep-alive> 优化网页性能
❓重复发送请求,性能上就会较低,有什么办法可以解决这个问题呢?
1️⃣程序的入口组件是 App 这个组件,所以我们打开 App.vue :
<template>
<div id="app">
<keep-alive> <!-- ❗️使用 keep-alive 标签包裹 router-view 标签(这是指:当这个路由被加载
过一次后,就把路由中的内容进行缓存,下次再进这个路由时,不需要再重新渲染、执行生命
周期函数,只需要从缓存中把之前的内容再显示出来即可。) -->
<router-view/>
</keep-alive>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
</style>
保存后,返回页面查看。当在首页刷新页面时,请求一次首页数据 index.json ;进入城市选择页时,请求一次城市数据 city.json ,之后切换路由都不再重复发送请求:
此时我们已经对性能上进行了优化,项目代码是否已经完美了呢?
其实还没有。
实际上,这里面还隐藏了一个问题。在实际的项目中,当我们切换“当前城市”后,首页的相关数据,都应该展示“当前城市”所对应的数据(即“当前城市”改变时,还应该发送一次请求,获取“新城市”的数据):
这就需要我们在发送 AJAX 请求时,带上“城市”的参数,去请求对应城市的数据。
2️⃣打开 home 下的 Home.vue :
<template>
<div>
<home-header></home-header>
<home-swiper :list="swiperList"></home-swiper>
<home-icons :list="iconList"></home-icons>
<home-recommend :list="recommendList"></home-recommend>
<home-weekend :list="weekendList"></home-weekend>
</div>
</template>
<script>
import HomeHeader from './components/Header'
import HomeSwiper from './components/Swiper'
import HomeIcons from './components/Icons'
import HomeRecommend from './components/Recommend'
import HomeWeekend from './components/Weekend'
import axios from 'axios'
import { mapState } from 'vuex' // 2️⃣-①:引入 mapState;
export default {
name: 'Home',
components: {
HomeHeader,
HomeSwiper,
HomeIcons,
HomeRecommend,
HomeWeekend
},
data () {
return {
swiperList: [],
iconList: [],
recommendList: [],
weekendList: []
}
},
computed: { // 2️⃣-②:添加一个计算属性,使用 mapState,获取到城市对应的内容;
...mapState(['city'])
},
methods: {
getHomeInfo () {
axios.get('/api/index.json?city=' + this.city) /*
2️⃣-③:发送 AJAX 请求时带上参数
city;
*/
.then(this.getHomeInfoSucc)
},
getHomeInfoSucc (res) {
res = res.data
if (res.ret && res.data) {
const data = res.data
this.swiperList = data.swiperList
this.iconList = data.iconList
this.recommendList = data.recommendList
this.weekendList = data.weekendList
}
}
},
mounted () {
this.getHomeInfo()
}
}
</script>
<style>
</style>
保存后,返回页面查看,当刷新页面时,发送的请求带上了当前城市“北京”:
但还有一个问题,在使用 <keep-alive> 标签后,只有在首次进入页面需要发送一次请求,之后切换页面时不再发送请求,而是使用缓存中的数据。
❓那么改变城市后,如何发送请求,再次获取对应城市的数据呢?
答:当我们使用 <keep-alive> 时,在组件中会有一个新的生命周期函数可以调用——activated,它会在切换组件(即切换页面)时执行。
我们在它执行前,判断“当前城市”是否与“最后选择的城市”不同。如果不同就在 activated 中再次发送请求,如果相同就依然使用缓存中的数据,不用发送请求。
3️⃣回到 home 下的 Home.vue :
<template>
<div>
<home-header></home-header>
<home-swiper :list="swiperList"></home-swiper>
<home-icons :list="iconList"></home-icons>
<home-recommend :list="recommendList"></home-recommend>
<home-weekend :list="weekendList"></home-weekend>
</div>
</template>
<script>
import HomeHeader from './components/Header'
import HomeSwiper from './components/Swiper'
import HomeIcons from './components/Icons'
import HomeRecommend from './components/Recommend'
import HomeWeekend from './components/Weekend'
import axios from 'axios'
import { mapState } from 'vuex'
export default {
name: 'Home',
components: {
HomeHeader,
HomeSwiper,
HomeIcons,
HomeRecommend,
HomeWeekend
},
data () {
return {
lastCity: '', /*
3️⃣-①:在 data 中定义一个变量 lastCity,初始化为空,
它表示最后一次选择的城市;
*/
swiperList: [],
iconList: [],
recommendList: [],
weekendList: []
}
},
computed: {
...mapState(['city'])
},
methods: {
getHomeInfo () {
axios.get('/api/index.json?city=' + this.city)
.then(this.getHomeInfoSucc)
},
getHomeInfoSucc (res) {
res = res.data
if (res.ret && res.data) {
const data = res.data
this.swiperList = data.swiperList
this.iconList = data.iconList
this.recommendList = data.recommendList
this.weekendList = data.weekendList
}
}
},
mounted () {
this.lastCity = this.city // 3️⃣-②:当页面被挂载后,让 lastCity 等于当前的 city;
this.getHomeInfo()
},
activated () { // 3️⃣-③:添加 activated 生命周期函数;
if (this.lastCity !== this.city) { // 3️⃣-④:如果 lastCity 不等于 city;
this.lastCity = this.city /*
3️⃣-⑤:就让 lastCity 等于 city(即,最后一次选择的城市不等于
当前城市时,让当前城市作为最后一次选择的城市);
*/
this.getHomeInfo() // 3️⃣-⑥:然后调用 getHomeInfo 重新发送请求。
}
}
}
</script>
<style>
</style>
保存后,返回页面查看。当首次进入首页时,请求一次数据;首次进入城市选择页时,请求一次城市数据。当在城市选择页选择相同城市时,不会发送请求;当切换为不同城市后,才再次发送请求、获取对应城市的数据:
以上,我们就完成了“首页”和“城市选择页”所有的功能。
祝好,qdywxs ♥ you!