分享微信小程序中實現sticky效果的(de)列表頁 - 新聞資訊 - 雲南小程序開發|雲南軟件開發|雲南網站建設-昆明融晨信息技術有限公司

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不(bù)管是(shì)網站,軟件還是(shì)小程序,都要(yào / yāo)直接或間接能爲(wéi / wèi)您産生價值,我們在(zài)追求其視覺表現的(de)同時(shí),更側重于(yú)功能的(de)便捷,營銷的(de)便利,運營的(de)高效,讓網站成爲(wéi / wèi)營銷工具,讓軟件能切實提升企業内部管理水平和(hé / huò)效率。優秀的(de)程序爲(wéi / wèi)後期升級提供便捷的(de)支持!

您當前位置>首頁 » 新聞資訊 » 小程序相關 >

分享微信小程序中實現sticky效果的(de)列表頁

發表時(shí)間:2022-9-14

發布人(rén):融晨科技

浏覽次數:217

首先什麽是(shì)sticky效果呢

具體參照餓了(le/liǎo)麽APP的(de)商品列表頁(小程序版本發現并未實現)
具體的(de)效果及實現可以(yǐ)查看一下這(zhè)個(gè)demo => sticky demo on codepen
簡單地(dì / de)說(shuō)就(jiù)是(shì)标題會有粘黏的(de)效果,向下滑動時(shí)跟着列表走,向上(shàng)滑動到(dào)頂部時(shí)将會固定在(zài)頂部。

但是(shì)如果在(zài)不(bù)考慮兼容性的(de)情況下(IOS6以(yǐ)上(shàng)、 Safari9.1+、 chrome56+)
其實從CSS3開始有一個(gè)position屬性sticky就(jiù)能實現這(zhè)種效果

{
    position: sticky;
    top: 0;
}

隻需要(yào / yāo)這(zhè)兩行就(jiù)能實現,然而(ér)...然而(ér)兼容性那是(shì)相當的(de)差,那麽好用的(de)一個(gè)屬性爲(wéi / wèi)什麽兼容性那麽差呢?

那麽餓了(le/liǎo)麽的(de)商品列表頁在(zài)小程序中實有哪些步驟呢?

  1. 利用scroll-view裏的(de)scroll-into-view屬性,具體可查看小程序的(de)文檔
  2. 實現sticky效果(可參照 codepen 的(de) demo)
  3. 獲取每個(gè)scroll-into-view的(de)scrollTop
  4. 監聽scroll的(de)滾動,并改變scroll-into-view

下來(lái)來(lái)讓我們看一下具體該如何實現

<scroll-view scroll-y class="left-wrapper" id="left">
  <view wx:for="..." bindtap="..."></view>
  <!--這(zhè)裏是(shì)左側的(de)類型選擇-->
</scroll-view>
<scroll-view scroll-y
             class="right-wrapper"
             bindscroll="onScroll"
             scroll-into-view="{{toView}}"
             id="right">
  <view wx:for="{{items}}" wx-for-item="item" class="lists" id="{{item.title}}">
    <view class="type-title" style="{{style}}">
      <!-- 這(zhè)個(gè)就(jiù)是(shì)ticky header部分 -->
      {{item.title}}
    </view>
    <view class="content">
      <view wx:for="{{item.child}}" class="item">
        <!--這(zhè)裏是(shì)需要(yào / yāo)展示具體的(de)列表項-->
      </view>
    </view>
  </view>
</scroll-view>

左側列表頁沒什麽好講的(de),無非就(jiù)是(shì)按下某個(gè)類型,給上(shàng)一個(gè)checked樣式,然後改變toView(關鍵)的(de)值。
那麽toView是(shì)什麽呢?toView的(de)值是(shì)和(hé / huò)scroll-view裏面你需要(yào / yāo)跳轉的(de)view的(de)id對應起來(lái)的(de),也(yě)就(jiù)是(shì)代碼中的(de)這(zhè)個(gè)id

<view wx:for="{{items}}" wx-for-item="item" class="lists" id="{{item.title}}">

所以(yǐ)當左側按下對應的(de)按鈕以(yǐ)後,右側的(de)scroll就(jiù)會跳轉到(dào)相應id的(de)scroll-into-view裏面,
其實到(dào)目前爲(wéi / wèi)止已經實現了(le/liǎo)sticky header + 跳轉的(de)問題了(le/liǎo)
但是(shì)...
如果滑動右側的(de)滾動條的(de)話,左側的(de)數據如何跟着變化呢?
假如不(bù)是(shì)小程序的(de)話應該很多人(rén)都知道(dào)怎麽做,無非就(jiù)是(shì)監聽滾動條,判斷滾動條的(de)位置,然後根據區域去改變左側的(de)選擇。
但是(shì)...
小程序如果獲得scroll-into-view在(zài)scroll-view裏面的(de)位置呢???
小程序是(shì)沒有類似document.getElementById()這(zhè)種Dom操作的(de)
也(yě)沒法使用JQuery的(de)$去快捷地(dì / de)獲取scrollTop的(de)
也(yě)不(bù)能像vue一樣直接操作$el的(de)
還好小程序在(zài)1.4時(shí)開放了(le/liǎo)一個(gè)接口wx.createSelectorQuery()

wx.createSelectorQuery()
返回一個(gè)SelectorQuery對象實例。可以(yǐ)在(zài)這(zhè)個(gè)實例上(shàng)使用select等方法選擇節點,并使用boundingClientRect等方法選擇需要(yào / yāo)查詢的(de)信息。


nodesRef.boundingClientRect([callback])
添加節點的(de)布局位置的(de)查詢請求,相對于(yú)顯示區域,以(yǐ)像素爲(wéi / wèi)單位。其功能類似于(yú)DOM的(de)getBoundingClientRect。返回值是(shì)nodesRef對應的(de)selectorQuery。
返回的(de)節點信息中,每個(gè)節點的(de)位置用left、right、top、bottom、width、height字段描述。如果提供了(le/liǎo)callback回調函數,在(zài)執行selectQuery的(de)exec方法後,節點信息會在(zài)callback中返回。
然後可以(yǐ)通過這(zhè)個(gè)方法拿到(dào)所有的(de)scroll-into-view的(de)位置

let query = wepy.createSelectorQuery()
for (let i = 0; i < this.types.length; ++i) {
  let id = this.types[i]
  query.select(`#${id}`).boundingClientRect((rect) => {
    this.scrollTops[id] = rect.top
  }).exec()
}

特别注意
這(zhè)個(gè)操作必須得放在(zài)onReady ()的(de)時(shí)候去做,否則将無法得到(dào)rect屬性
得到(dào)這(zhè)個(gè)屬性以(yǐ)後其實就(jiù)很好操作了(le/liǎo),直接上(shàng)代碼了(le/liǎo)

onScroll (event) {
  // 如果是(shì)右側的(de)滾動view
  if (event.currentTarget.id === 'right') {
    // 判斷滾動的(de)方向
    let top = event.detail.scrollTop
    this.dir = this.currentTop < top ? 'down' : 'up'
    this.currentTop = top
    // 判斷當前滾動條所在(zài)區域,如果不(bù)在(zài)當前區域則進行跳轉
    if (top > this.scrollTops[this.getNextView()] &&
        this.dir === 'down' &&
        this.checked < this.types.length - 1) {
      this.setChecked(this.checked + 1)
    }
    if (top < this.scrollTops[this.toView] &&
        this.dir === 'up' &&
        this.checked > 0) {
      this.setChecked(this.checked - 1)
    }
  }
}

然後一個(gè)簡單的(de)具有sticky效果的(de)商品列表頁跳轉功能就(jiù)實現了(le/liǎo)。

  1. scroll-view必須設置高度,否則在(zài)IOS上(shàng)将無法使用scroll-into-view跳轉
  2. 使用createSelectorQuery必須在(zài)頁面渲染完成以(yǐ)後

存在(zài)問題

  1. scroll會有個(gè)慣性運動,這(zhè)時(shí)候按左側的(de)按鈕切換scroll-into-view會和(hé / huò)onScroll事件發生一些沖突,測試IOS存在(zài)有該問題,希望大(dà)神給予些指導意見。

說(shuō)明

由于(yú)采用了(le/liǎo)wepy構建的(de)小程序,所以(yǐ)在(zài)部分代碼上(shàng)會和(hé / huò)小程序有出(chū)入(改過一些),主要(yào / yāo)是(shì)思路。
順便丢個(gè)wepy的(de)github
wepy的(de)本意是(shì)希望小程序能像vue一樣開發,由于(yú)本人(rén)一直在(zài)用vue做項目,所以(yǐ)用wepy開發小程序會順手一些,但是(shì)wepy雖然盡力貼合vue,但在(zài)某些設計上(shàng)存在(zài)着一定的(de)問題,但相對來(lái)說(shuō)比直接開發小程序用起來(lái)舒服一些。

相關案例查看更多