注意:若是gif動態圖看不了,麻煩你們點擊github美團項目中mt-app/src/assets/美團.gif即可以觀看!html
本項目很適合vue初學者,若是業務邏輯看不懂,很歡迎一塊兒討論!vue
源碼地址:mt-app,歡迎 star 和 forkwebpack
若是對你有些許幫助,不妨點贊、關注我一下啊ios
一言而蔽之:一款集點菜、用戶評價和商家信息爲一體的移動端點餐APP
1.點餐頁面
點選商品後自動添加到購物車,並計算好總價,在商品列表、購物車列表和商品詳情頁均可以隨意增減數目,此外左側商品分類和右側的商品相互關聯,經過better-scroll插件滑動商品列表時,相應的商品分類也會跟着跳轉。
2.用戶評價頁面
主要包括一個TAB欄,包括三部分:所有、有圖和評價三個模塊
3.商家信息頁面
主要介紹一些商家基本信息,能夠經過better-scroll插件,進行左右滑動圖片git
該項目業務邏輯主要集中在點餐模塊,而點餐模塊中難點即是如何實現商品列表滑動,以及右側商品分類和左側商品列表如何聯動?github
首先要實現商品列表的滑動,就須要用到一個better-scroll插件,better-scroll 是一款重點解決移動端(已支持 PC)各類滾動場景需求的插件。web
npm install better-scroll --save
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) }