頁面包括三個(gè)部分,當(dāng)前城市宙址,熱門城市和城市滾動(dòng)欄轴脐。城市的信息都是通過axios請(qǐng)求json文件再渲染的。滾動(dòng)部分和字母表部分用到了一個(gè)插件抡砂,這部分也是我感覺最困難的地方大咱。
1.axios請(qǐng)求數(shù)據(jù)
跟之前一樣,在city.vue里發(fā)送總請(qǐng)求舀患,得到的數(shù)據(jù)可以傳給子組件徽级,避免了每個(gè)組件都要發(fā)送請(qǐng)求,減少請(qǐng)求數(shù)量聊浅。
mounted
鉤子在掛載好后自動(dòng)調(diào)用函數(shù)getCityInfo()
,成功后調(diào)用函數(shù)handleGetCityInfoSucc
餐抢,函數(shù)接收res
參數(shù),一開始我還不太明白這段代碼意思低匙,后來在控制臺(tái)輸出了一下res就明白了旷痕。
getCityInfo(){
axios.get('/api/city.json')
.then(this.handleGetCityInfoSucc)
},
handleGetCityInfoSucc(res){
res=res.data
if(res.ret && res.data){
const data=res.data
this.cities=data.cities
this.hotCities=data.hotCities
}
},
看一下控制臺(tái)中res輸出:
首先
res=res.data
將res指向res.data部分,此時(shí)的res包括data顽冶、ret和--proto--三部分欺抗,如果res.ret==true并且res.data不為空,將data指向res中的data部分强重。同樣獲取到data中的cities和hotCities部分绞呈。
2.父子組件數(shù)據(jù)傳遞
給子組件綁定屬性,子組件通過props接收 间景,懂自懂佃声,不多說=。=
有一個(gè)地方需要注意 Cities是對(duì)象 hotCities是數(shù)組倘要,在列表渲染的時(shí)候圾亏,對(duì)于數(shù)組可以(item,index)這樣取屬性,對(duì)于對(duì)象需要(item,key)取屬性,key代表“A志鹃、B夭问、C...”等地區(qū)首字母,對(duì)象啊 是以鍵值對(duì)存儲(chǔ)的
<div class="area"
v-for="(item,key) of cities"
:key="key" :ref="key">
<div class="title border-top-bottom">{{key}}</div>
......
3. 組件數(shù)據(jù)傳遞——字母列表部分【難點(diǎn)-邏輯比較繞】
3.1 點(diǎn)擊字母列表中字母曹铃,列表滾動(dòng)到相應(yīng)位置
先搞清楚缰趋,Alphabet.vue和 List.vue是兄弟組件關(guān)系,都屬于City.vue的子組件铛只。
要完成點(diǎn)擊字母表埠胖,列表跟著滾動(dòng)的功能糠溜,需要組件之間通信淳玩。
在父組件City中定義的數(shù)據(jù)有cities hotCities和letter,前兩個(gè)數(shù)據(jù)都通過axios獲取到了非竿,而letter在這里定義蜕着,通過Alphabet接收,傳給List使用红柱。
data(){
return {
cities:{},
hotCities:[],
letter:''
}
},
Alphabet組件給字母表中每個(gè)字母都綁定了一個(gè)點(diǎn)擊事件@click="handleLetterClick"
承匣。當(dāng)點(diǎn)擊li,通過$emit向外發(fā)送該字母到父組件锤悄,實(shí)現(xiàn)子組件向父組件傳遞數(shù)據(jù)韧骗。
handleLetterClick(e){
this.$emit('change',e.target.innerText)
},
父組件通過 @change="handleLetterChange">
事件接收,在函數(shù)里接收到點(diǎn)擊的字母零聚,賦值給letter
handleLetterChange(letter){
this.letter=letter
}
父組件得到letter后袍暴,傳給List,List里定義一個(gè)watch函數(shù)隶症,隨時(shí)監(jiān)聽letter的變化政模,當(dāng)letter非空時(shí),使用better-scroll將列表滾動(dòng)到相應(yīng)的位置
letter() {
// 如果字符非空蚂会,會(huì)自動(dòng)滾到字符開頭的位置
if(this.letter){
// better-scroll參數(shù)需要使用dom
const element=this.$refs[this.letter][0] //dom形式
this.scroll.scrollToElement(element)
}
}
剛開始覺得有點(diǎn)復(fù)雜淋样,但是多想幾遍流程就想清楚了
3.2 滑動(dòng)字母列表中字母,列表滾動(dòng)到相應(yīng)位置
在Alphabet組件中綁定幾個(gè)函數(shù) 胁住,在move中先計(jì)算A到頂部的距離趁猴,再計(jì)算手指點(diǎn)到頂部距離,相減得到與A的相對(duì)距離彪见,除以每個(gè)li的高度儡司,得到index,發(fā)送letters[index]到change事件企巢。
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
@click="handleLetterClick">
handleTouchMove(e){
// 當(dāng)狀態(tài)等于true時(shí)才對(duì)執(zhí)行move事件
if(this.touchStatus){
const startY=this.$refs["A"][0].offsetTop //dom元素
const touchY= e.touches[0].clientY-80
const index=Math.floor((touchY-startY)/20)
if(index >= 0 && index < this.letters.length){
this.$emit("change",this.letters[index])
}
}
3.3 offsetTop和ClientY區(qū)別 以及其他滾動(dòng)代碼的常用屬性
【坑 等填】