微信小程序實現點餐小程序左側滑動菜單

前言

最近在幫親戚做一款微信的點餐小程序,以前從沒有接觸過小程序的我隻能現做現賣。一邊看文檔一邊實踐嘗試,在進行到點菜模塊左側滑動菜單時遇到瞭小小的阻礙。索性在查找一些資料和教程後主要功能實現瞭出來。特此記錄下,也希望能幫助到需要做同樣功能的同學。

效果圖:

一、初識scroll-view

想要實現上述功能我們必須要借助微信為我們提供的scroll-view組件,沒有瞭解過的同學需要先去簡單閱讀下API。從圖中我們可以看出整個佈局主要是由左右兩個滾動界面構成。但是它們彼此之間又有聯系,在點擊左側菜單類型跟滑動右側菜品的時候另外一個滾動窗口必須做出響應。滾動條實現原理其實就是我們HTML中的錨點,右側整個菜單是一個完整界面它會將其按唯一id標識拆分成不同模塊。比如我們整個界面的高度是2000rpx,其中人氣top10占400rpx。那麼height:0-400就對應人氣top10。而無肉不歡對應模塊高度為300rpx那麼,400-700區域就是無肉不歡。以此類推,下面代碼中我們使用id="{{ ‘right’ + item.id}}" 為每個分類模塊做瞭唯一標識。

<view>
  <view class="menuMain">
    <scroll-view scroll-y="true" class="menuLeft">
      <view wx:for="{{menuArr}}" wx:key="*this" bindtap="leftMenuClick" data-current_index="{{index}}" class="{{leftView == index ? 'active' : ''}}">{{item.name}}

      </view>
    </scroll-view>
    <scroll-view scroll-y="true" scroll-with-animation="true" bindscroll="rightScroll" scroll-into-view="{{rightId}}"
     class="menuRight">
      <view  wx:for="{{menuArr}}" wx:key="*this" id="{{ 'right' + item.id}}" class="goods">
        <view class="goodsType">
         ---  {{item.name}} ---
        </view>
        <view wx:for="{{item.subArr}}" wx:key="*this" wx:for-item="goods" class="goodsContent">
          <view class="orderDishes">
            <image src="{{goods.imageUrl}}" ></image>
            <view class="goodsInfo">
              <view class="goodsInfo">{{goods.goodsName}}</view>
              <view class="goodsInfo">規格:{{goods.unit}}</view>
              <view class="goodsInfo goodsInfoPrice">¥{{goods.price}}</view>
              <view class="add">
                +
              </view>
            </view>
          </view>
        </view>
      </view>
    </scroll-view>
  </view>


</view>

二、左側導航

在小程序初始化生命周期函數onReady中我們需要提前獲取不同模塊的高度並存入數組中,來為我們後續跳轉提供高度信息。我們分段將所有的view對應高度都放入到heightArr 數組中。首先實現左側點擊導航右側滑動到對應高度需求,這裡使用bindtap微信我們提供的綁定事件函數來控制右側的位置。這裡我們為for循環參數index進行瞭重命名,通過自定義屬性data-傳遞給函數調用者。這裡需要註意一個屬性scroll-into-view。值應為某子元素id(id不能以數字開頭)。設置哪個方向可滾動,則在哪個方向滾動到該元素 其對應的view標識id就是當前右側滑動窗口要顯示的內容,所以我們需要將左側屬性與右側視圖id對應起來。在data中我們定義兩個字段leftView代表左側人氣top10,無肉不歡等分類導航。rightId對應scroll-view標簽下各個view的唯一id值。這裡註意我們的id並不是直接對應,前面有right字段使用是需要進行組合。點擊左側控制右側滑動的功能並不需要用到高度數組,隻需要使其與view中的id對應起來即可。詳細請看leftMenuClick函數。為瞭使動畫看起來比較流暢請加上scroll-with-animation屬性

let heightArr = [0]  // 存放高度累加數組
data: {
    rightId: 'right0',
    leftView: 0
  },
/**
   * 生命周期函數--監聽頁面初次渲染完成
   */
  onReady: function () {
    const query = wx.createSelectorQuery()
    query.selectAll('.goods').boundingClientRect()
    query.selectViewport().scrollOffset()
    query.exec(function (res) {
      res[0].top // #the-id節點的上邊界坐標
      res[1].scrollTop // 顯示區域的豎直滾動位置
      res[0].map( val => {
        let result = val.height  + heightArr[heightArr.length - 1]
        console.log(result)
        // 拿後一個view盒子的高度加上前面的高度
        heightArr.push(result) 
      })
      console.log(heightArr)
    })
  
  },
/**
   * 左側菜單點擊事件,事件對象e傳輸index
   */
  leftMenuClick(e){
    console.log(e.currentTarget.dataset.current_index)
    this.setData({
      leftView: e.currentTarget.dataset.current_index,
      rightId: 'right' + e.currentTarget.dataset.current_index
    })
  },

  /**
   * 右側滾動事件
   */
  rightScroll(e) {
    let st = e.detail.scrollTop
    console.log('st' + e.detail.scrollTop)
    for(let i = 0; i < heightArr.length; i++){
      if(st >= heightArr[i] && st <= heightArr[i+1] - 5){
        this.setData({
          leftView: i,
        })
        console.log(this.data.leftView)
        return
      }
    }
  }

三、右側滑動

右側滑動控制左側菜單自動選擇就需要用到我們前面說到的滑動高度瞭,上面我們獲取到瞭每個view對應的高度分別存儲到瞭heightArr 數組中。數組中存放的每個數值對應的是我們view所在高度。e.detail.scrollTop獲取到的是頂部界面所屬高度,假設當前頂部高度為500我們知道400-700是屬於無肉不歡對應的界面。此時隻需要判斷後將leftView修改為所對應的2即可。具體實現看rightScroll函數,我們遍歷循環heightArr中的高度數值判斷當前st屬於哪個階層,找到後將左側標識字段設置為對應值即可。其中我們 -5是為瞭使用戶體驗更友好避免出現分類標題已經劃過去瞭,左側導航還沒變更的情況。大體邏輯就是這樣,樣式根據自己需求來就可以。下面給出我實現界面對應的代碼,其中很多樣式都是偽代碼大傢到時自信更改。

/* pages/order/order.wxss */

.link {
  height: 30px;
}

.mainMenu {
  width: 180rpx;
}

.menuMain {
  height: 100vh;
  display: flex;
  flex-direction: row;
  justify-content: space-around;
}

/* 左側菜單導航欄 */
.menuLeft {
  width: 20%;
}

.menuLeft view {
  font-size: 26rpx;
  text-align: center;
  height: 100rpx;
  line-height: 100rpx;
  background-color: rgb(238, 241, 241);
  position: relative;
}
.menuLeft view.active{
  background-color: rgb(255, 255, 255);
}

.menuLeft view::before {
  content: '';
  width: 6rpx;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;
  background-color:transparent;
  border-left: none;
}

.menuLeft view.active::before {
  background-color: rgb(245, 229, 6);
}


.menuRight {
  height: 100vh;
  width: 75%;
}

.menuRight .goods{
  padding: 10rpx;
}

.menuRight .goodsType{
  text-align: center;
  height: 60rpx;
  line-height: 60rpx;
  font-weight: 600;
  color: rgb(0, 0, 0);
}

.menuRight .goods .goodsContent .orderDishes image{
  width: 320rpx;
  height: 260rpx;
}


.menuRight .goods .goodsContent text{
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.orderDishes{
  padding-top: 20rpx;
  display: flex;
  flex-direction: row;
}

.add{
  margin-left: 40rpx;
  margin-top: 10rpx;
  width: 120rpx;
  font-size: 40rpx;
  font-weight: 600;
  height: 40rpx;
  line-height: 40rpx;
  text-align: center;
  background-color: rgb(219, 80, 55);
  border-radius: 20rpx;
  color: rgb(255, 255, 255);
}

.goodsInfo{
  margin-left: 16rpx;
  height: 65rpx;
  font-size: 28rpx;
  font-weight: 800;
  color: rgb(0, 0, 0);
}


.goodsInfoPrice{
  color: rgb(247, 36, 36);
}

以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。

推薦閱讀: