【vue/axios/vue-router】製做一個精緻的美團項目

1、項目展現:

美團

注意:若是gif動態圖看不了,麻煩你們點擊github美團項目中mt-app/src/assets/美團.gif即可以觀看!html

本項目很適合vue初學者,若是業務邏輯看不懂,很歡迎一塊兒討論!vue

源碼地址:mt-app,歡迎 star 和 forkwebpack

若是對你有些許幫助,不妨點贊、關注我一下啊ios

2、項目涉及到技術棧:

  • vue全家桶:Vue、Vue-router、Vue-cli等
  • 組件化:單Vue文件
  • 模塊化:ES6 Module
  • 第三方模塊:better-scroll axios等
  • 基礎開發環境和包管理:Node、npm
  • 構建工具:webpack
  • 編輯器:webstrom

3、項目主要功能

一言而蔽之:一款集點菜、用戶評價和商家信息爲一體的移動端點餐APPgit

  1. 點餐頁面 點選商品後自動添加到購物車,並計算好總價,在商品列表、購物車列表和商品詳情頁均可以隨意增減數目,此外左側商品分類和右側的商品相互關聯,經過better-scroll插件滑動商品列表時,相應的商品分類也會跟着跳轉。
  2. 用戶評價頁面 主要包括一個TAB欄,包括三部分:所有、有圖和評價三個模塊
  3. 商家信息頁面 主要介紹一些商家基本信息,能夠經過better-scroll插件,進行左右滑動圖片

4、項目難點

該項目業務邏輯主要集中在點餐模塊,而點餐模塊中難點即是如何實現商品列表滑動,以及右側商品分類和左側商品列表如何聯動?github

首先要實現商品列表的滑動,就須要用到一個better-scroll插件,better-scroll 是一款重點解決移動端(已支持 PC)各類滾動場景需求的插件。web

  • 安裝better-scroll npm install better-scroll --save
  • 在Good.vue文件中script引入import BScroll from 'better-scroll'

這些準備工做作好後,實現左右兩邊列表聯動,總結起來有如下四個步驟: 1. 計算商品分類的區間高度npm

//template部分
  <!--商品列表-->
    <div class="foods-wrapper" ref="foodScroll">
      <ul>
        <!--專場-->
        <li class="container-list food-list-hook">
          <div v-for="(item,index) in container.operation_source_list" :key="index">
            <img :src="item.pic_url">
          </div>
        </li>
        <!-- 具體分類 -->
        <li v-for="(item,index) in goods" :key="index" class="food-list food-list-hook">
          <h3 class="title">{{item.name}}</h3>
          <!-- 具體的商品列表 -->
          <ul>
            <li v-for="(food,index) in item.spus" :key="index" @click="showDetail(food)" class="food-item">
            ......
複製代碼
//JS部分
methods:{
  calculateHeight() {   // 計算分類的區間總高度(包括專場和全部具體分類的總高)
        let foodlist = this.$refs.foodScroll.getElementsByClassName("food-list-hook")
        let height = 0
        this.listHeight.push(height)
        for (let i = 0; i < foodlist.length; i++) {
          let item = foodlist[i]
          height += item.clientHeight    // 累加
          this.listHeight.push(height)
        }
        console.log(this.listHeight)//[0, 43, 1231, 2401, 3589, 4451, 6121, 7656, 8497, 9344, 10080]
      },
   initScroll() {
        this.menuScroll = new BScroll(this.$refs.menuScroll, {  //實例化
          click: true  //點擊事件才能生效
        })
        this.foodScroll = new BScroll(this.$refs.foodScroll, {
          probeType: 3,
          click: true
        })
},
   created() {
      fetch("/api/goods")
        .then(res => res.json())
        .then(response => {
          if (response.code == 0) {
           this.container = response.data.container_operation_source
           this.goods = response.data.food_spu_tags
           this.poiInfo = response.data.poi_info 
           this.$nextTick(() => {  //在created中數據雖已初始化,但dom未生成,頁面還沒顯示,要使用回調函數,確保DOM已經更新
           this.initScroll()        // 執行滾動方法
           this.calculateHeight() //調用計算分類區間高度的方法
            })
          }
        })
    }
複製代碼

2. 監聽滾動的位置json

initScroll() {
        this.menuScroll = new BScroll(this.$refs.menuScroll)
        this.foodScroll = new BScroll(this.$refs.foodScroll, {
          probeType: 3,//在屏幕滑動的過程當中實時派發 scroll 事件
         click:true//點擊事件才能生效
        })
        //foodScroll監聽事件
        this.foodScroll.on("scroll", (pos) => {
          this.scrollY = Math.abs(pos.y)
          console.log(this.scrollY)
        })
      }
複製代碼

3. 根據滾動位置確認下標,與左側對應axios

computed:{
    currentIndex(){
      for(let i = 0; i < this.listHeight.length; i++){
        let height1 = this.listHeight[i]
        let height2 = this.listHeight[i+1] // 獲取商品區間的範圍
        if(!height2 || (this.scrollY >= height1 && this.scrollY < height2)){
          return i;    // 是否在上述區間中
        }
      }
      return 0
    }
複製代碼
<li class="menu-item"
          :class="{'current':currentIndex === 0}"//動態綁定一個樣式,.current設置樣式
          @click="selectMenu(0)">
          <p class="text">
            <img class="icon" :src="container.tag_icon" v-if="container.tag_icon">
            {{container.tag_name}}
          </p>
        </li>
        <li class="menu-item"
            :class="{'current':currentIndex === index + 1}"
            v-for="(item,index) in goods" :key="index"
            @click="selectMenu(index+1)"
            >
複製代碼

4. 經過下標實現點擊左側,滾動右側

<li class="menu-item" :class="{'current':currentIndex===0}" @click="selectMenu(0)">
<li class="menu-item" :class="{'current':currentIndex===index+1}" 
v-for="(item,index) in goods" :key="index" @click="selectMenu(index+1)">//同一個函數傳值不同
複製代碼
selectMenu(index) {
        let foodlist = this.$refs.foodScroll.getElementsByClassName("food-list-hook")
        let element = foodlist[index]
        this.foodScroll.scrollToElement(element, 250)
      }
複製代碼

5、項目總結

  • vue數據和視圖的分離,以數據驅動視圖,只關心數據變化,DOM操做被封裝,在實際開發過程當中大大提升了效率。
  • Vue的組件化功能可謂是它的一大亮點,經過將頁面上某一組件的html、CSS、JS代碼放入一個.vue的文件中進行管理能夠大大提升代碼的維護性。
  • 項目中未作移動端適配,在不一樣屏幕手機上打開,可能用戶體驗會差些
相關文章
相關標籤/搜索