10-1.city頁(yè)面路由配置
1.添加路由配置
// router/index.js文件
import City from '@/pages/city/City'
export default new Router({
routes: [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/city',
name: 'City',
component: City
}
]
})
2.添加相對(duì)應(yīng)的頁(yè)面
在pages文件下面添加city文件夾和City.vue文件
3.初始化City.vue頁(yè)面
<template>
<div>
city
</div>
</template>
<script>
export default {
name: 'City'
}
</script>
<style lang="stylus" scoped>
</style>
10-2.city-header部分制作
//city/City.vue
<template>
<div>
<city-header></city-header>
</div>
</template>
<script>
import CityHeader from './components/Header'
export default {
name: 'City',
components: {
CityHeader
}
}
</script>
<style lang="stylus" scoped>
</style>
//city/components/header.vue
<template>
<div class="header">
城市選擇
<router-link to="/">
<div class="iconfont back-city"></div>
</router-link>
</div>
</template>
<script>
export default {
name: 'CityHeader'
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.header
position relative
height $headHeight
line-height $headHeight
background $bgColor
text-align center
color #ffffff
.back-city
position absolute
left 0
top 0
width .64rem
text-align center
padding 0 .1rem
font-size .48rem
color #fff
</style>
10-3.city-search部分制作
上面咱們已經(jīng)完成了頭部的制作,這一節(jié)咱們來(lái)city-search的ui部分制作,隨后等咱們把city列表制作完成后,咱們?cè)賮?lái)制作city-search相關(guān)的邏輯部分,代碼如下
//city/components/Search.vue
<template>
<div class="search">
<input class="search-input" type="text" placeholder="輸入城市名稱或者拼音" />
</div>
</template>
<script>
export default {
name: 'CitySearch'
}
</script>
<style lang="stylus" scoped>
@import '~styles/varibles.styl'
.search
height .722rem
padding 0 .1rem
background $bgColor
.search-input
box-sizing border-box
width 100%
height .62rem
padding 0 .1rem
line-height .62rem
border-radius .06rem
color #666
text-align center
</style>
city/City.vue,在city的主頁(yè)面引入我們制作好的city-search模塊
10-4 city-list、city-ajax 、city-vuex、city-search-logic 部分的制作
Ui上面的制作,直接從github下載下來(lái),git checkout 到不同的分支,就能看到代碼了,總結(jié)嘛,不能能把所有的項(xiàng)目中的代碼都展示出來(lái),更多的是展示難點(diǎn)、思路、注意事項(xiàng)等等一些小細(xì)節(jié)地方。
city-ajax部分和index-ajax 方式是一樣,在這里咱們就不再次贅述了
知識(shí)點(diǎn)1:BetterScroll 的使用,讓城市列表可以滾動(dòng)起來(lái)
//安裝better-scroll
npm install better-scroll -S
在這個(gè)使用better-scroll的時(shí)候我們需要注意三點(diǎn)
- dom結(jié)構(gòu)(要符合這種結(jié)構(gòu))
<div class="wrapper">
<ul class="content">
<li>...</li>
<li>...</li>
...
</ul>
<!-- you can put some other DOMs here, it won't affect the scrolling
</div>
- 樣式(要滾動(dòng)的list 要脫離文檔流)
.list
overflow: hidden;
position: absolute;
top: 1.6rem;
left: 0;
right: 0;
bottom: 0;
- 在vue中的調(diào)用和使用方法
//dom部分
<div class="list" ref="wrapper">
.....
</div>
//js部分
import BScroll from 'better-scroll'
mounted () {
this.scroll = new BScroll(this.$refs.wrapper)
}
知識(shí)點(diǎn)2兄弟組件數(shù)據(jù)傳遞
我們知道:
City.vue是父組件
components/List.vue是一個(gè)子組件
components/Alphabet.vue也是一個(gè)子組件
那么子組件(Alphabet.vue)如何和子組件(List.vue)進(jìn)行通信呢?
現(xiàn)在有這樣的一個(gè)需求,就是當(dāng)我們點(diǎn)擊右側(cè)的字母(代碼在Alphabet.vue中),列表(List.vue)能自動(dòng)滾動(dòng)相對(duì)應(yīng)的列表字母模塊部分,那么這個(gè)過(guò)程就是一個(gè)子組件和子組件的通信(兄弟組件數(shù)據(jù)傳遞)
思路:
第一步:子組件(Alphabet.vue)點(diǎn)擊字母的時(shí)候,通過(guò)$emit發(fā)送一個(gè)'change'的方法,并且把攜帶的點(diǎn)擊入?yún)鬟f給父組(City.vue)
//dom部分
<li
class="item"
v-for="item of letters"
:key="item"
@click="handleLetterClick" //觸發(fā)點(diǎn)擊事件
>{{item}}</li>
//js部分
methods: {
handleLetterClick (e) {
this.$emit('change', e.target.innerText)
}
}
第二步:父組件(City.vue)通過(guò)屬性來(lái)監(jiān)聽(tīng)‘change’事件,同時(shí)創(chuàng)建一個(gè)新的方法,在此方法中來(lái)接受子組件傳遞過(guò)來(lái)的參數(shù),隨后把入?yún)⒎湃氲絛ata初始化的letter中,再然后,把letter獲得入?yún)⒁詫傩缘姆绞絺鬟f給city-list組件
//1)dom 來(lái)監(jiān)聽(tīng)子組件發(fā)出來(lái)的change
<city-alphabet :cities="cities" @change="handleLetterClick"></city-alphabet>
//4)dom 父組件從子組件那拿來(lái)的數(shù)據(jù)(letter)傳遞給新的子組件
<city-list :cities="cities" :hotCities="hotCities" :letter="letter"></city-list>
//2)初始化data中的letter值 用來(lái)存儲(chǔ)子組件出來(lái)的入?yún)?data () {
return {
letter: ''
}
},
//3)js change 創(chuàng)建的方法 來(lái)接受子組件傳遞過(guò)來(lái)的值,并把它存儲(chǔ)到data里面
handleLetterClick (letter) {
this.letter = letter
}
第三步:子組件(List.vue)通過(guò)屬性props來(lái)接受父組件傳過(guò)來(lái)的值
//js
props: {
letter: String//接受父組件傳遞過(guò)來(lái)的值
},
//js 監(jiān)聽(tīng)傳過(guò)來(lái)值的變化
watch: {
letter () {
if (this.letter) {
const element = this.$refs[this.letter][0] //通過(guò)獲取字母的值
this.scroll.scrollToElement(element) //滾動(dòng)到指定元素模塊
}
}
}
//dom 需要在字母模塊添加ref屬性
<div
class="area"
v-for="(item,key) of cities"
:key="key"
:ref="key"http://這個(gè)key值剛好和兄弟組件傳過(guò)來(lái)的值相同
>
<div class="title border-topbottom">{{key}}</div>
<div class="item-list">
<div class="item border-bottom" v-for="innerItem of item" :key="innerItem.id">{{innerItem.name}}</div>
</div>
</div>
知識(shí)點(diǎn)3 完成一個(gè)手指滑動(dòng)右側(cè)字母,左側(cè)區(qū)域跟著滾動(dòng)
這部分咱們需要給右側(cè)的字母綁定上三個(gè)事件:
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
為了只讓在touchmove里面去觸發(fā)這些操作,所以我們需要定義個(gè)開(kāi)關(guān)(標(biāo)示位),我們把這個(gè)標(biāo)示位放在了data里面
touchStatus: false //設(shè)置為false
所以當(dāng)我們開(kāi)始滑動(dòng)的時(shí)候我們把touchStatus設(shè)置為true
handleTouchStart () {
this.touchStatus = true
}
當(dāng)我們手指劃出觸發(fā)操作區(qū)域的時(shí)候,我們需要把標(biāo)示為設(shè)置為false
handleTouchEnd () {
this.touchStatus = false
}
所以只有當(dāng)標(biāo)示位為true的這種情況,我們采取進(jìn)滑動(dòng)字母相對(duì)應(yīng)的操作
handleTouchMove () {
if (this.touchStatus) {
//滑動(dòng)過(guò)程中所對(duì)應(yīng)的邏輯
}
}
思路
在滑動(dòng)這個(gè)過(guò)程中,最終我們?cè)谶@個(gè)頁(yè)面上下滑動(dòng)的時(shí)候,我們需要知道你滑動(dòng)的位置是第幾個(gè)字母
1、我們需要知道A字母距離頂部的距離
2、我們需要知道手指滑動(dòng)到當(dāng)前字母距離頂部的的距離
3、把上面兩個(gè)做一個(gè)差值,那么我們就可以得到當(dāng)前位置距離A字母之間的高度
4、我們把得到這個(gè)差值高度除以每個(gè)字母的高度,那么我們就得到了是第幾個(gè)字母了
根據(jù)上面這個(gè)思路,我們需要得到這個(gè)字母的數(shù)組:
computed: {
letters () {
const letters = []
for (let i in this.cities) {
letters.push(i)
}
return letters
}
}
通過(guò)計(jì)算屬性,我們就可以把dom上的數(shù)據(jù)獲取從父組件傳遞過(guò)來(lái)的cities改為letters
<li
class="item"
v-for="item of letters" //通過(guò)計(jì)算屬性來(lái)獲得字母值
:key="item"
:ref="item"
@click="handleLetterClick"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
>
{{item}}
</li>
根據(jù)上面的思路咱們開(kāi)始來(lái)編寫相對(duì)應(yīng)邏輯
handleTouchMove (e) {
//標(biāo)示位開(kāi)始
if (this.touchStart) {
const startY = this.$refs['A'].offsetTop //獲取字母A距離頂部的距離
const touchY = e.touches[0].clientY - 79 //獲取手機(jī)滑動(dòng)當(dāng)前字母距離頂部距離(79是header和搜索框的高度)
const index = Math.floor((touchY-startY) / 20) //獲得是第幾個(gè)字母
if (index >= 0 && index < this.letters.length) {
this.$emit('change', this.letters[index]) //在有效的索引里面去 查找是第幾個(gè)字母
}
}
}
其實(shí)寫到這塊我們的功能是完成了的,但是細(xì)想還有一些地方需要優(yōu)化?
初始化
data () {
return {
startY: 0,
timer: null
}
},
優(yōu)化一:每次都去求獲取字母A距離頂部的距離?
updated () {
this.startY = this.$refs['A'][0].offsetTop
},
優(yōu)化二:滑動(dòng)字母的時(shí)候,需要做一下事件節(jié)流(通過(guò)一個(gè)定時(shí)器timer)
handleTouchMove (e) {
if (this.touchStatus) {
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
const startY = this.startY
const touchY = e.touches[0].clientY - 79
const index = Math.floor((touchY - startY) / 20)
if (index >= 0 && index < this.letters.length) {
this.$emit('change', this.letters[index])
}
}, 16)
}
},
知識(shí)點(diǎn)4 實(shí)現(xiàn)一個(gè)城市搜索功能
需求
1.根據(jù)字母或者漢字可以進(jìn)行檢索想要的內(nèi)容
2.當(dāng)搜索框沒(méi)數(shù)據(jù)的時(shí)候,不顯示搜索區(qū)域內(nèi)容
3.當(dāng)搜索框有數(shù)據(jù)且數(shù)據(jù)不在搜索內(nèi)容時(shí),顯示暫無(wú)搜索內(nèi)容
4.當(dāng)搜索出來(lái)的內(nèi)容比較多的時(shí)候,搜索內(nèi)容可以進(jìn)行滾動(dòng)(better-scroll)
第一步:獲取從父組件傳遞過(guò)來(lái)的cities值
props: {
cities: Object
},
第二步:data里面初始化keyword、list、timer
data () {
return {
keyword: '',
list: [],
timer: null
}
},
第三步:watch方法監(jiān)聽(tīng)keyword的更改、其中這里面包含timer優(yōu)化、list數(shù)據(jù)獲取、檢索操作的邏輯
watch: {
keyword () {
if (this.timer) {
clearTimeout(this.timer)
}
if (!this.keyword) {
this.list = []
return false
}
this.timer = setTimeout(() => {
const result = []
for (let i in this.cities) {
this.cities[i].forEach(value => {
if (value.spell.indexOf(this.keyword) > -1 || value.name.indexOf(this.keyword) > -1) {
result.push(value)
}
})
}
this.list = result
}, 100)
}
},
第四步:數(shù)據(jù)處理好了,要鋪到Ui上面
為了可以滾動(dòng):一定要符合better-scroll的dom結(jié)構(gòu);search-content樣式要脫離文檔流。
只有當(dāng)有關(guān)鍵字才會(huì)顯示搜索內(nèi)容;
當(dāng)關(guān)鍵字搜索沒(méi)有數(shù)據(jù)的時(shí)候,顯示”沒(méi)有搜索到匹配內(nèi)容“
<div class="search-content" ref="search" v-show="keyword">
<ul>
<li class="search-item border-bottom" v-for="item of list" :key="item.id">{{item.name}}</li>
<li class="search-item border-bottom" v-show="hasNoData">沒(méi)有搜索到匹配內(nèi)容</li>
</ul>
</div>
第五步:搜索數(shù)據(jù)有了,但是過(guò)多的時(shí)候也要可以滾動(dòng),better-scroll
mounted () {
this.scroll = new Bscroll(this.$refs.search)
}
知識(shí)點(diǎn)5 vuex實(shí)現(xiàn)數(shù)據(jù)共享
如果學(xué)過(guò)react的同學(xué)肯定知道redux,react是處理ui層的,那么數(shù)據(jù)層就是通過(guò)redux來(lái)完成,方便我們不同頁(yè)面之間的傳值,一直值的更改等等
同樣在vue中,vue也只負(fù)責(zé)ui部分,vuex則是用來(lái)處理數(shù)據(jù)層的
1.安裝vuex
npm install vuex -S
2.使用和調(diào)用vuex
因?yàn)関uex是處理數(shù)據(jù)模塊的,所以我們?cè)趕rc目錄下創(chuàng)建一個(gè)store目錄,在store目錄下面創(chuàng)建一個(gè)
index.js
import Vue from 'vue'
import Vuex from 'vuex'
export default new Vuex.Store({
state: {
city: '北京'
}
})
創(chuàng)建好之后,我們?cè)趍ain.js文件中去調(diào)用這個(gè)文件
import store from './store'
new Vue({
el: '#app',
store,//根實(shí)例引入store
router,
components: { App },
template: '<App/>'
})
3.應(yīng)用
在咱們這個(gè)項(xiàng)目中,首頁(yè)右上角的城市名稱是通過(guò)后端返給我們,那么我們可以通過(guò)vuex來(lái)初始化一個(gè)城市,也可以通過(guò)vuex來(lái)更改城市這個(gè)值。
在store/index.js 其實(shí)我們已經(jīng)做了city的初始化的值:北京
那么在首頁(yè)和城市頁(yè)面我們?nèi)绾潍@取vuex當(dāng)中這個(gè)值呢?
//pages/home/components/Header.vue
{{this.$store.state.city}}
//pages/city/components/List.vue 當(dāng)前城市
{{this.$store.state.city}}
點(diǎn)擊熱門城市或者點(diǎn)擊城市搜索出來(lái)列表切換城市的顯示,那么我們?nèi)ト绾胃膕tate這個(gè)值呢?
//點(diǎn)擊熱門城市事件
@click="handleCityClick(item.name)"
methods: {
handleCityClick (city) {
//要調(diào)用store里面的dispatch方法
this.$store.dispatch('changeCity', city)
}
}
上面我們已經(jīng)觸發(fā)了一個(gè)dispatch的方法,那么我們通過(guò)actions來(lái)接受這個(gè)方法
store/index.js
export default new Vuex.Store({
state: {
city: '上海'
},
actions: {
changeCity(ctx, city) {
//console.log(city)
//那么action如何調(diào)用mutations呢?通過(guò)commit方法
ctx.commit('changeCity',city)
}
},
mutations: {
changeCity (state, city) {
state.city = city
}
}
})
從上面可以看出在我們發(fā)送dispatch的時(shí)候,并沒(méi)有觸發(fā)異步請(qǐng)求,或者批量的數(shù)據(jù)操作,所以上面操作,我們可以直接跳過(guò)actions這部分,不需要去觸發(fā)dispatch操作,而是直接調(diào)用commit對(duì)mutations的操作
所以上面的代碼就可以改為:
//點(diǎn)擊熱門城市事件
@click="handleCityClick(item.name)"
methods: {
handleCityClick (city) {
//要調(diào)用store里面的dispatch方法
this.$store.commit('changeCity', city) //將dispatch 改為commit
}
}
//store/index.js
export default new Vuex.Store({
state: {
city: '上海'
},
//刪除actions的相關(guān)操作
mutations: {
changeCity (state, city) {
state.city = city
}
}
})
講到這里其實(shí)就實(shí)現(xiàn)了vuex的數(shù)據(jù)一個(gè)設(shè)置以及顯示的一些操作,但是我們更具當(dāng)前的產(chǎn)品需求我們還是需要完善一下頁(yè)面跳轉(zhuǎn)。
之前我們實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)是通過(guò)
1.router-link 的to屬性來(lái)實(shí)現(xiàn)
2.那么還有一種通過(guò)js 來(lái)實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)的$router.push
那么我們希望我們?cè)谶x擇完城市后,能自動(dòng)跳轉(zhuǎn)到首頁(yè),那么
this.$router.push('/')
知識(shí)點(diǎn)6 vuex的高級(jí)使用以及l(fā)ocalStorage
store/index.js文件的拆分和localStorage的應(yīng)用
在上面使用vuex中我們給city設(shè)置了一個(gè)初始值:'上海',但是當(dāng)我們切換完城市后,返回首頁(yè),如果我們刷新首頁(yè),那么我們選擇的城市就又變回為了默認(rèn)值:'上海',那么針對(duì)這種情況,我們需要引入本地緩存localStorage,但是呢,有些瀏覽器會(huì)屏蔽localStorage的一些東西,為了程序的健壯性,減少?zèng)]必要的瀏覽器異常,所以在對(duì)localStorage進(jìn)行相關(guān)操作的時(shí)候,我們先進(jìn)行一層try catch的操作
//store/index.js
let defaultCity = '上海'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {}
export default new Vuex.Store({
state: {
city: defaultCity
},
mutations: {
changeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) {}
}
}
})
寫到這里我們發(fā)現(xiàn),將來(lái)如果我們業(yè)務(wù)比較復(fù)雜的話,store/index.js會(huì)變的越來(lái)越龐大,那么這不是我們希望看到的,所以我們要對(duì)store/index.js進(jìn)行拆分。
那么如何進(jìn)行拆分呢?
store/index.js 只是一個(gè)總文件,而這個(gè)總文件包含很多部分:state、actions、mutations等等,
那么我們將可以將這些模塊拆分成為:state.js、actions.js、mutations.js
最后再把他們引入到store/index.js文件中
那么,根據(jù)這個(gè)思路咱們接下來(lái)拆分一下store/index.js
//store/state.js
let defaultCity = '北京'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {
}
export default {
city: defaultCity
}
//store/mutions.js
export default{
changeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) {}
}
}
那么store/index.js 就變?yōu)榱耍?/p>
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
Vue.use(Vuex)
export default new Vuex.Store({
state,
mutations
})
vuex的高級(jí)應(yīng)用以及針對(duì)項(xiàng)目當(dāng)中的優(yōu)化
我們上面調(diào)用城市的時(shí)候是通過(guò){{this.$store.state.city}}
來(lái)實(shí)現(xiàn)的
如果這么寫的話,略顯頁(yè)面比較冗余。那么有沒(méi)有其他方法會(huì)比較簡(jiǎn)單一些呢?
vuex幫我們封裝了一些方法和aip有一個(gè)mapState的方法就可以幫我們實(shí)現(xiàn),那么應(yīng)該如何使用呢?
import { mapState } from 'vuex'
//第一種通過(guò)數(shù)組方法獲取
computed: {
...mapState(['city']) //這樣就把把store中的city值獲取到
}
//第二種通過(guò)對(duì)象方法獲?。ㄆ鹨粋€(gè)別名)
computed: {
...mapState({
currentCity: 'city'
}) //這樣就把把store中的city值獲取到
}
//如果是第一種方法獲取的
將原來(lái)的 {{this.$store.state.city}} 改為 {{this.city}}
//如果是第二種方法獲取的
將原來(lái)的 {{this.$store.state.city}} 改為 {{this.currentCity}}
獲取vuex中store的數(shù)據(jù)我們可以通過(guò)mapState方法,那么設(shè)置vuex數(shù)據(jù)呢?
我們可以通過(guò)vuex給我們提供的mapMutations方法,那么如何實(shí)現(xiàn)呢?
import {mapMutations} from 'vuex'
methods: {
handleCityClick (city) {
//this.$store.commit('changeCity', city) 改為下面:
this.changeCity(city)
this.$router.push('/')
},
...mapMutations(['changeCity'])
}
講的這里我們使用了vuex給我們提供的state、actions、mutations,我們登錄vue官網(wǎng),我們發(fā)現(xiàn)vuex還給我們提供了兩個(gè)一個(gè)是getter、另一個(gè)是module
那么我們來(lái)看一下getter的使用
//store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
Vue.use(Vuex)
export default new Vuex.Store({
state,
mutations,
getters: {
doubleCity (state) {
return state.city + ' ' + state.city
}
}
})
那么頁(yè)面上應(yīng)該如何使用或者調(diào)用呢?
import { mapGetters } from 'vuex'
computed: {
...mapGetters(['doubleCity'])
}
//頁(yè)面上調(diào)用
{{this.doubleCity}}
那么我們此時(shí)會(huì)想,這有什么用處呢?因?yàn)閙apState就可以實(shí)現(xiàn)的方法,我為什么還要使用mapGetters來(lái)實(shí)現(xiàn)呢?
其實(shí)呢,我們發(fā)現(xiàn)getters方法有點(diǎn)類似vue組件當(dāng)中的computed方法,他可以把我們state值進(jìn)行處理后返給我們一個(gè)新值,從來(lái)來(lái)避免一些數(shù)據(jù)的冗余。
getter講完了,那么module我們?cè)谑裁辞闆r下去使用呢?
因?yàn)槲覀冊(cè)趕tore/index.js中 只寫了city相關(guān)的(state、actions、mutations)等等操作,當(dāng)我們?cè)趯?shí)際開(kāi)發(fā)的過(guò)程中,我們肯定不單單只有city這一個(gè)模塊的,如果有很多頁(yè)面的功能模塊的話,我們拆分的state.js、actions.js、mutations.js會(huì)變得很臃腫的,這不是我們期盼看到的。
所以我們通過(guò)module模塊對(duì)我們的功能模塊進(jìn)行進(jìn)一步的拆分,每個(gè)功能模塊包含自己的(state、actions、mutations等等)。如下面例子:
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的狀態(tài)
store.state.b // -> moduleB 的狀態(tài)
知識(shí)點(diǎn)7 使用keep-alive優(yōu)化網(wǎng)頁(yè)
keep-alive是個(gè)抽象組件(或稱為功能型組件),實(shí)際上不會(huì)被渲染在DOM樹(shù)中。它的作用是在內(nèi)存中緩存組件(不讓組件銷毀),等到下次再渲染的時(shí)候,還會(huì)保持其中的所有狀態(tài),并且會(huì)觸發(fā)activated鉤子函數(shù)。因?yàn)榫彺娴男枰ǔ3霈F(xiàn)在頁(yè)面切換時(shí),所以常與router-view一起出現(xiàn):
//app.vue
<keep-alive>
<router-view/>
</keep-alive>
如此一來(lái),每一個(gè)在router-view中渲染的組件,都會(huì)被緩存起來(lái)。
如果只想渲染某一些頁(yè)面/組件,可以使用keep-alive組件的include/exclude屬性。include屬性表示要緩存的組件名(即組件定義時(shí)的name屬性),接收的類型為string、RegExp或string數(shù)組;exclude屬性有著相反的作用,匹配到的組件不會(huì)被緩存。假如可能出現(xiàn)在同一router-view的N個(gè)頁(yè)面中,我只想緩存列表頁(yè)和詳情頁(yè),那么可以這樣寫:
<keep-alive :include="['Home', 'City']">
<router-view />
</keep-alive>
那么針對(duì)咱們這個(gè)項(xiàng)目,當(dāng)我們?cè)黾由蟢eep-alive屬性后,當(dāng)我們?cè)L問(wèn)過(guò)的頁(yè)面請(qǐng)求過(guò)后,再去請(qǐng)求的時(shí)候,那么就不會(huì)再去觸發(fā)ajax請(qǐng)求,而在此項(xiàng)目中首頁(yè)的數(shù)據(jù)變更是需要我們切換不同的城市來(lái)實(shí)現(xiàn)變更的,也就是當(dāng)城市只要變更我們就需要對(duì)首頁(yè)數(shù)據(jù)進(jìn)行一次請(qǐng)求。那么我們應(yīng)該如何更新首頁(yè)的數(shù)據(jù)呢?
//通過(guò)vuex的mapState屬性我們可以獲取 city的值
import { mapState } from 'vuex'
computed: {
...mapState(['city'])
},
//通過(guò)ajax的入?yún)?lái)請(qǐng)求不同城市的數(shù)據(jù)
getHomeInfo () {
axios.get('/api/index.json?city=' + this.city).then(this.getHomeInfoSucc)
},
//當(dāng)我們觸發(fā)了keep-alive屬性后,那么就會(huì)多出一個(gè)activated的生命周期鉤子
//通過(guò)城市的變更,我們?cè)谶@個(gè)生命周期函數(shù)中再去請(qǐng)求接口,入?yún)⒂米钚碌某鞘校敲丛趺磥?lái)區(qū)分城市的變更呢?
//data里面定義一個(gè)新的字段lastCity
data () {
return {
lastCity: '',//定義
swiperList: [],
iconList: [],
recommendList: [],
weekendList: []
}
},
//如果當(dāng)前的city和最后一次請(qǐng)求的城市不一致,那么我們把最后一次請(qǐng)求的城市賦值為最新的城市,且用最新的城市作為接口請(qǐng)求的入?yún)?activated () {
if (this.lastCity !== this.city) {
this.lastCity = this.city
this.getHomeInfo()
}
}
更多
上一篇:第9章 Vue項(xiàng)目開(kāi)發(fā)之首頁(yè)
下一篇:第11章 Vue項(xiàng)目開(kāi)發(fā)之詳情
全篇文章:Vue學(xué)習(xí)總結(jié)
所有章節(jié)目錄:Vue學(xué)習(xí)目錄