首頁 > 軟體

微信小程式實現點餐小程式左側滑動選單

2022-07-17 18:01:36

前言

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

效果圖:

一、初識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);
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com