首先什么是sticky效果呢具體參照餓了么APP的商品列表頁(小程序版本發現并未實現)具體的效果及實現可以查看一下這個demo = sticky demo on codepen簡單地說就是標題會有粘黏的效果,向下滑動時跟著列表走,向上滑動 ...
具體參照餓了么APP的商品列表頁(小程序版本發現并未實現)
具體的效果及實現可以查看一下這個demo => sticky demo on codepen
簡單地說就是標題會有粘黏的效果,向下滑動時跟著列表走,向上滑動到頂部時將會固定在頂部。
但是如果在不考慮兼容性的情況下(IOS6以上、 Safari9.1+、 chrome56+)
其實從CSS3開始有一個position屬性sticky就能實現這種效果
{
position: sticky;
top: 0;
}
只需要這兩行就能實現,然而...然而兼容性那是相當的差,那么好用的一個屬性為什么兼容性那么差呢?
<scroll-view scroll-y class="left-wrapper" id="left">
<view wx:for="..." bindtap="..."></view>
<!--這里是左側的類型選擇-->
</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}}">
<!-- 這個就是ticky header部分 -->
{{item.title}}
</view>
<view class="content">
<view wx:for="{{item.child}}" class="item">
<!--這里是需要展示具體的列表項-->
</view>
</view>
</view>
</scroll-view>
左側列表頁沒什么好講的,無非就是按下某個類型,給上一個checked樣式,然后改變toView(關鍵)的值。
那么toView是什么呢?toView的值是和scroll-view里面你需要跳轉的view的id對應起來的,也就是代碼中的這個id
<view wx:for="{{items}}" wx-for-item="item" class="lists" id="{{item.title}}">
所以當左側按下對應的按鈕以后,右側的scroll就會跳轉到相應id的scroll-into-view里面,
其實到目前為止已經實現了sticky header + 跳轉的問題了
但是...
如果滑動右側的滾動條的話,左側的數據如何跟著變化呢?
假如不是小程序的話應該很多人都知道怎么做,無非就是監聽滾動條,判斷滾動條的位置,然后根據區域去改變左側的選擇。
但是...
小程序如果獲得scroll-into-view在scroll-view里面的位置呢???
小程序是沒有類似document.getElementById()這種Dom操作的
也沒法使用JQuery的$去快捷地獲取scrollTop的
也不能像vue一樣直接操作$el的
還好小程序在1.4時開放了一個接口wx.createSelectorQuery()
wx.createSelectorQuery()
返回一個SelectorQuery對象實例。可以在這個實例上使用select等方法選擇節點,并使用boundingClientRect等方法選擇需要查詢的信息。
nodesRef.boundingClientRect([callback])
添加節點的布局位置的查詢請求,相對于顯示區域,以像素為單位。其功能類似于DOM的getBoundingClientRect。返回值是nodesRef對應的selectorQuery。
返回的節點信息中,每個節點的位置用left、right、top、bottom、width、height字段描述。如果提供了callback回調函數,在執行selectQuery的exec方法后,節點信息會在callback中返回。
然后可以通過這個方法拿到所有的scroll-into-view的位置
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()
}
特別注意
這個操作必須得放在onReady ()的時候去做,否則將無法得到rect屬性
得到這個屬性以后其實就很好操作了,直接上代碼了
onScroll (event) {
// 如果是右側的滾動view
if (event.currentTarget.id === 'right') {
// 判斷滾動的方向
let top = event.detail.scrollTop
this.dir = this.currentTop < top ? 'down' : 'up'
this.currentTop = top
// 判斷當前滾動條所在區域,如果不在當前區域則進行跳轉
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)
}
}
}
然后一個簡單的具有sticky效果的商品列表頁跳轉功能就實現了。
由于采用了wepy構建的小程序,所以在部分代碼上會和小程序有出入(改過一些),主要是思路。
順便丟個wepy的github
wepy的本意是希望小程序能像vue一樣開發,由于本人一直在用vue做項目,所以用wepy開發小程序會順手一些,但是wepy雖然盡力貼合vue,但在某些設計上存在著一定的問題,但相對來說比直接開發小程序用起來舒服一些。