Vue2.5仿去哪兒app筆記二——swiper的自動構建 傳送ajax請求 父子元件傳值 兄弟元件間資料傳遞
swiper的自動構建 傳送ajax請求 父子元件傳值 兄弟元件間資料傳遞
swiper的自動構建
在首頁的icon頁面下,預設一個頁面中包括8個圖示。而我們希望若當頁面中有9個圖示時,可以左右拖動,形成輪播圖的效果。而且我們希望頁面能夠自動計算和適配圖示與輪播圖,當圖示數目變化時,輪播圖也跟著相應變化。
所以應該設定兩個v-for指令。分別遍歷頁面與圖示。
<swiper-slide v-for="(page,index) of pages" :key="index">
<div class="icon" v-for="item of page" :key="item.id">
<div class="icons">
<swiper>
<swiper-slide v-for="(page,index) of pages" :key="index">
<!--包括兩個v-for指令,第一個是根據頁面數,在pages中遍歷每一個輪播圖頁面。-->
<div class="icon"
v-for="item of page"
:key="item.id">
<!--第二個是在一個頁面(page)內遍歷8個圖示-->
<div class="icon-img">
<img class="icon-img-content" :src='item.imgUrl' alt="">
</div>
<p class="icon-text">{{item.icontext}}</p>
</div>
</swiper-slide>
</swiper>
</div>
利用計算屬性,來實現根據圖示數目自動構建頁碼,實現多頁切換的輪播圖效果。
computed: {
pages () {
const pages = []
this.iconList.forEach((item, index) => {
const page = Math.floor(index / 8)//向下取整
// 計算當前index所處頁面page,一個頁面包括8個icons
if (!pages[page]) {
pages[page] = []
// 當前page溢位,新建頁面
}
pages[page].push(item)
})
return pages
// 根據資料自動構建頁碼,實現多頁切換的輪播圖
}
}
使用axios傳送ajax請求
axios 是一個基於Promise 用於瀏覽器和 nodejs 的 HTTP 客戶端
對於home頁面來說,每一個元件都有自己的資料,但為避免多次請求降低效能,所以希望整個首頁只發送一個ajax請求,並且在home.vue
傳送一個ajax請求在獲取資料之後,能分別把資料傳給每一個子元件。
//home.vue
methods: {
getHomeInfo () {
axios.get('/api/index.json').then(this.getHomeInfoSucc)
//這裡的get路徑為'/api/index.json'
//但本地的模擬資料在'/static/mock'目錄下,需要藉助路徑代理
},
getHomeInfoSucc (res) {
res = res.data
//獲取資料
if (res.ret && res.data) {
//後端正確返回結果
const data = res.data
this.city = data.city
this.swiperList = data.swiperList
this.iconList = data.iconList
this.recommendList = data.recommendList
this.weekendList = data.weekendList
//傳遞資料
}
}
},
mounted () {
this.getHomeInfo()
//藉助mounted生命週期函式,讓頁面掛載好之後執行該函式
}
因為只有在/static
目錄下的內容可以被外部訪問到,所以將本地模擬資料放在./static/mock
目錄下,並且在配置項中新增代理路徑
//index.js
proxyTable: {
'/api': {
target: 'http://localhost:8080',
pathRewrite: {
'^/api': '/static/mock'
}
}
},
父子元件間傳值
在父元件中,宣告引入子元件,並傳入子元件內需要的值
//home.vue
data () {
//初始化資料
return {
city: '',
swiperList: [],
iconList: [],
recommendList: [],
weekendList: []
}
},
子元件接收資料,註冊props
//component.vue
props: {
recommendList: Array
//或 city: String
}
在主頁面繫結每個元件
<!--home.vue-->
<!--父元件用屬性的方式向子元件傳值-->
<div class="">
<home-header :city="city"></home-header>
<home-swiper :list='swiperList'></home-swiper>
<!--把父元件獲取到的資料賦給子元件-->
<home-icons :iconList='iconList'></home-icons>
<home-recommend :recommendList='recommendList'></home-recommend>
<home-weekend :weekendList='weekendList'></home-weekend>
</div>
swiper輪播圖預設顯示最後一張圖片問題
當使用axios傳送ajax請求後,會發現當頁面載入完成後,輪播圖預設會顯示最後一張圖片
這是因為頁面還沒有獲取ajax資料時,props的list接收的是外部空陣列,即最初建立時是通過空陣列建立,獲取完成ajax後,獲取真正的資料,才重新渲染新資料。
解決方法:
讓swiper的初次建立由完整的資料建立,而不使用空陣列建立。
即當List為空陣列時,不顯示輪播圖。
<swiper :options="swiperOption" v-if="showSwiper">
...
</swiper>
computed: {
showSwiper () {
return this.list.length
//也可直接使用v-if="list.length"
//但儘量不在模板內新增邏輯性的程式碼,所以新增一個計算屬性來判斷資料
}
}
兄弟元件間資料傳遞
實現右側字母列表與城市列表同步
要實現當點選某個字母時,頁面自動跳轉到該字母對應的城市列表,需實現Alphabet.vue
與list.vue
這兩個兄弟元件間的資料傳遞。
對於非父子元件傳值,可藉助父元件進行間接傳遞,即先將Alphabet.vue
傳給city.vue
,city.vue
再轉發給list.vue
Alphabet.vue傳給city.vue(子元件向父元件傳值)
//Alphabet.vue
handleClick (e) {
this.$emit('change', e.target.innerText)
//為字母繫結一個click事件,當點選時向外觸發事件,事件的名字為‘change’,攜帶的內容即為這個字母
}
向外觸發事件後,父元件city.vue
監聽這個事件
<cityAlphabet :cities="cities" @change="handleClick"></cityAlphabet>
handleClick (letter) {
this.letter = letter
//接收Alphabet.vue傳遞過來的letter
}
city.vue將接收到的letter轉發給list.vue(父元件向子元件傳值)
<!--city.vue-->
<list :cities="cities" :hotCities="hotCities" :letter="letter"></list>
在list.vue中,藉助監聽器watch來監聽letter的變化,並使頁面隨letter的改變而改變
<div class="area" v-for="(item,key) of cities" :key="key" :ref="key">
watch: {
letter () {
if (this.letter) {
// const element = this.$refs[this.letter]
// 此時element是一個數組,而不是一個DOM元素
const element = this.$refs[this.letter][0]
this.scroll.scrollToElement(element)
//讓滾動區自動滾動到element對應的DOM元素上
}
}
}
其中
ref 被用來給元素或子元件註冊引用資訊。引用資訊將會註冊在父元件的 refs是一個物件,即持有註冊過ref特性的所有DOM元素和元件例項。