注意:項目講解案例參照之前的博客,如有不理解的地方,請按vue學習總結順序查看。
如果從頭到尾仔細閱讀過我之前博客的朋友可能發現,我在講vue生命週期的時候並沒有詳細的去講activated以及deactivated這兩個生命週期函數,在接下來的這篇博客中會爲大家揭開它的神祕面試。
我會把列表頁好詳情頁的數據替換成動態請求的數據,而不是寫死在data函數裏面,當然因爲沒有接口,我只能通過本地的json數據來模擬
首頁修改一下config文件夾下面的index.js文件裏面的配置,如下:
其次,我們要用到數據請,在這裏我採用vue官方推薦的axios插件,執行命令npm install axios
此時axios已經安裝成功了,我們可以在list頁面發起網絡請求了(請求的是本地的istatic文件夾下的ndex.json文件)
//static-->mock-->index.json
{
"ret": true,
"data": {
"list": [{
"id": "1",
"name": "蘋果",
"detail":""
},{
"id": "2",
"name": "香蕉"
},{
"id": "3",
"name": "梨子"
},{
"id": "4",
"name": "葡萄"
},{
"id": "5",
"name": "哈密瓜"
},{
"id": "6",
"name": "西瓜"
},{
"id": "7",
"name": "橙子"
}]
}
}
list.vue代碼如下:
<template>
<ul class="list-page">
<li v-for="item in list" :key="item.id" :id="item.id" @click="goDetail">{{item.name}}</li>
</ul>
</template>
<script>
import axios from 'axios'
export default {
name: 'List',
data(){
return {
list:[]
}
},
mounted(){
this.getData();//調用獲取數據函數
},
methods:{
//定義頁面跳轉函數
goDetail(e){
const id=e.currentTarget.getAttribute("id");
const name=e.currentTarget.innerText;
this.$router.push({
path:'detail',
query:{id:id, name:name}
})
},
//定義獲取數據函數
getData(){
axios.get('/api/index.json').then((res)=>{
if(res.status==200){
this.list=res.data.data.list;
}
}).catch((error)=>{
console.log(error);
})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="stylus" scoped>
.list-page
font-size 0.26rem
li
height 0.7rem
line-height 0.7rem
background-color white
border-bottom 1px solid #ececec
padding-left 0.2rem
</style>
再看看頁面是否請求到了數據,打開頁面的network,查看網絡請求如下:
我們可以看出請求已經成功,並且頁面頁渲染了,但是我們在反覆進入列表頁面看看會發生什麼情況?
由此可知,用戶每次進入頁面都會發起一個請求,這樣對網頁性能優化是不利的,那怎樣可以避免這種情況呢?vue推薦在<routr-view/>組件上面包裹一層keep-alive組件,如圖:
//App.vue
<template>
<div id="app">
<keep-alive>
<router-view/>
</keep-alive>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
</style>
接下來我麼你在看看反覆進入list頁面還會不會發起網絡請求:實踐證明無論進入多少次列表頁都只會發起一起請求,這樣在數據沒有發生改變的情況下可以大大降低網絡請求的時間從而提高網站性能
我們再思考一下,雖然這樣我們把所有的頁面都基於緩存了不用發起第二次請求,但是對於某些頁面來說,如動態路由,需要根據接收的不同參數來獲取不同的數據那怎麼辦呢?
其實vue2.0版本後,keep-alive內置組件已經封裝了兩個屬性,include和exclude表示那些組件需要緩存那些組件不需要緩存,用法大致如下:
<keep-alive include="test-keep-alive">
<!-- 將緩存name爲test-keep-alive的組件 -->
<component></component>
</keep-alive>
<keep-alive include="a,b">
<!-- 將緩存name爲a或者b的組件,結合動態組件使用 -->
<component :is="view"></component>
</keep-alive>
<!-- 使用正則表達式,需使用v-bind -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>
<!-- 動態判斷 -->
<keep-alive :include="includedComponents">
<router-view></router-view>
</keep-alive>
<keep-alive exclude="test-keep-alive">
<!-- 將不緩存name爲test-keep-alive的組件 -->
<component></component>
</keep-alive>
還有一種方法我們可以動態配置路由,來確定那些路由需要緩存哪些不需要緩存,這樣的話就需要修改route文件下的index.js文件:
import Vue from 'vue'
import Router from 'vue-router'
/*import Home from '@/containers/home/index'
import List from '@/containers/list/index'
import Detail from '@/containers/detail/index'
import Person from '@/containers/person/index'*/
const Home = resolve => require(['@/containers/home/index'], resolve);
const List = resolve => require(['@/containers/list/index'], resolve);
const Detail = resolve => require(['@/containers/detail/index'], resolve);
const Person = resolve => require(['@/containers/person/index'], resolve);
Vue.use(Router);
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home ,
meta: {
keepAlive: true // 需要被緩存
}
},{
path: '/list',
name: 'List',
component: List,
meta: {
keepAlive: true // 需要被緩存
}
},{
path: '/detail',
name: 'Detail',
component: Detail,
meta: {
keepAlive: false // 不需要被緩存
}
},{
path: '/person',
name: 'Person',
component: Person,
meta: {
keepAlive: true // 需要被緩存
}
},
]
})
然後在app,vue文件下修改一下keep-alive組件的用法,這樣是不是寫起來很方便呢?
//App.vue
<template>
<div id="app">
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
</style>
注意一點:activated,deactivated這兩個生命週期函數一定是要在使用了keep-alive組件後纔會有的,否則則不存在