1. 程式人生 > >Vue2.5仿去哪兒app筆記二——swiper的自動構建 傳送ajax請求 父子元件傳值 兄弟元件間資料傳遞

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.vuelist.vue這兩個兄弟元件間的資料傳遞。
對於非父子元件傳值,可藉助父元件進行間接傳遞,即先將Alphabet.vue傳給city.vuecity.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 被用來給元素或子元件註冊引用資訊。引用資訊將會註冊在父元件的 r e f s D O M 使 D O M . refs 物件上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子元件上,引用就指向元件例項. 而 refs是一個物件,即持有註冊過ref特性的所有DOM元素和元件例項。