vue前端框架vueuse的useScroll函數(shù)使用源碼分析
引言
頁面很多時候都含有可滾動視圖區(qū)域,可能是橫向滾動也可能是縱向滾動。
- 有時我們需要知道當前的滾動方向,是向左還是向右,是向上還是向下;
- 有時需要知道當前是否是正在滾動,如果滾動則顯示一個加載動畫等;
- 有時我們還需要知道滾動條是否已經(jīng)滾動到了上下左右的邊界。
如果我們自己來實現(xiàn)這一系列的邏輯判斷可能也不難,但是如何優(yōu)雅地實現(xiàn)以便于更方便地使用呢?一起研究一下vueuse的useScroll函數(shù)吧~
1.示例
vueuse官方文檔給出了useScroll函數(shù)的demo, 我們可以在線操作看一下效果:
如上圖所示,當向下滑動或者拖拽豎直方向的滾動條時則isScrolling為true表示正在向下滾動,同時useScroll能夠識別出滾動方向為向下。
如上圖所示,當滾動條觸底的時候,useScroll能夠識別出已經(jīng)到達了底部。
useScroll為何如此好用,是如何實現(xiàn)的呢?我們一同學習其源碼。
2.源碼解析
先看折疊后的代碼整體了解一下:
我們發(fā)現(xiàn)整個代碼流程包括了參數(shù)的解析,狀態(tài)的定義,滾動結束回調函數(shù),滾動監(jiān)聽處理函數(shù),最后是返回值,我們依次來看一下。
2.1 參數(shù)解析
const { throttle = 0, idle = 200, onStop = noop, onScroll = noop, offset = { left: 0, right: 0, top: 0, bottom: 0, }, eventListenerOptions = { capture: false, passive: true, }, } = options
useScroll接受兩個參數(shù),第一參數(shù)為目標元素,也就是監(jiān)聽哪一個元素的滾動事件;第二個參數(shù)為options,涵蓋其他的選項。我們來詳細地看一下這些選項的含義:
- throttle 滾動事件的節(jié)流事件,默認不對滾動事件節(jié)流,所以throttle的默認值為0。
- idle 滾動結束時的檢查事件,這個值會和throttle 加在一起對滾動結束事件進行防抖,分析后面的代碼時會看到
- onStop 滾動結束時觸發(fā)的回調函數(shù)
- onScroll 滾動時觸發(fā)的回調函數(shù)
- offset 定義滾動條到達上下左右邊界的一個偏移值,單位為像素。例如left設置為30, 則水平滾動條距離左邊界30px時則認為到達了左邊界。
- eventListenerOptions 滾動事件監(jiān)聽器的選項
2.2 響應式狀態(tài)定義
const x = ref(0) const y = ref(0) const isScrolling = ref(false) const arrivedState = reactive({ left: true, right: false, top: true, bottom: false, }) const directions = reactive({ left: false, right: false, top: false, bottom: false, })
定義響應式變量x用于記錄上次滾動的scrollLeft的值;
y記錄上次滾動的scrollTop的值;
isScrolling表示是否正在滾動。
arrivedState提供了水平方向滾動條距離左邊和右邊的距離以及垂直方向滾動條距離上邊和下邊的距離。
directions用于描述當前滾動的方向。
2.3 onScrollEnd滾動結束回調
const onScrollEnd = useDebounceFn((e: Event) => { isScrolling.value = false directions.left = false directions.right = false directions.top = false directions.bottom = false onStop(e) }, throttle + idle)
滾動結束回調函數(shù)使用了useDebounceFn進行防抖。當滾動結束后,isScrolling賦值為false, 滾動方向全部賦值為false, 調用onStop回調。
2.4 onScrollHandler滾動處理
const onScrollHandler = (e: Event) => { const eventTarget = ( e.target === document ? (e.target as Document).documentElement : e.target ) as HTMLElement const scrollLeft = eventTarget.scrollLeft directions.left = scrollLeft < x.value directions.right = scrollLeft > x.value arrivedState.left = scrollLeft <= 0 + (offset.left || 0) arrivedState.right = scrollLeft + eventTarget.clientWidth >= eventTarget.scrollWidth - (offset.right || 0) x.value = scrollLeft let scrollTop = eventTarget.scrollTop // patch for mobile compatible if (e.target === document && !scrollTop) scrollTop = document.body.scrollTop directions.top = scrollTop < y.value directions.bottom = scrollTop > y.value arrivedState.top = scrollTop <= 0 + (offset.top || 0) arrivedState.bottom = scrollTop + eventTarget.clientHeight >= eventTarget.scrollHeight - (offset.bottom || 0) y.value = scrollTop isScrolling.value = true onScrollEnd(e) onScroll(e) }
onScrollHandler用于處理滾動。首先是水平方向滾動方向與是否到達左右邊界的判斷。說明如下:
(1)獲取當前的scrollLeft和上一次的scrollLeft也就是x.value進行比較,如果scrollLeft < x.value說明向左滾動,否則向右滾動。
(2)如何判斷是否到達左邊界?這里考慮到了偏移量offset.left。如果當前的scrollLeft <= offset.left就認為到達了左邊界。
(3)是否到達右邊界要看當前滾動的距離+元素視口的寬度(clientWidth)是否大于整個內(nèi)容的寬度(scrollWidth)減去偏移量的值(offset.right)
豎直方向的判斷同理,不再贅述,如果您不熟悉clientWidth、scrollWidth的含義,您可以閱讀筆者之前的文章:scrollTop、clientHeight、 scrollHeight...學完真的理解了。
滾動的時候還需要調用onScrollEnd觸發(fā)滾動結束事件,調用onScroll回調函數(shù),將isScrolling設置為true。
2.5 使用 useEventListener監(jiān)聽滾動事件
useEventListener( element, 'scroll', throttle ? useThrottleFn(onScrollHandler, throttle) : onScrollHandler, eventListenerOptions, )
使用useEventListener監(jiān)聽scroll事件,如果需要節(jié)流則回調函數(shù)為useThrottleFn包裝過的onScrollHandler,否則直接使用onScrollHandler。
2.6 返回值
return { x, y, isScrolling, arrivedState, directions, }
useScroll最后返回響應式狀態(tài)。我們使用一張圖總結一下這些狀態(tài):
3.總結
useScroll提供了響應式的滾動位置和狀態(tài)。滾動位置包括水平方向和垂直方向的滾動位置;滾動狀態(tài)包括是否在滾動,是否到達了上下左右的邊界,當前滾動的方向。useScroll使用useEventListener來監(jiān)聽滾動事件,在滾動事件的監(jiān)聽回調函數(shù)中修改狀態(tài)和位置。在其計算位置的源碼部分我們需要了解clientWidth、scrollWidth、clientHeight、scrollHeight這些值的含義。
以上就是vueuse的useScroll函數(shù)源碼分析的詳細內(nèi)容,更多關于vueuse useScroll函數(shù)的資料請關注腳本之家其它相關文章!
相關文章
vue+vuex+axio從后臺獲取數(shù)據(jù)存入vuex實現(xiàn)組件之間共享數(shù)據(jù)
這篇文章主要介紹了vue+vuex+axio從后臺獲取數(shù)據(jù)存入vuex,組件之間共享數(shù)據(jù),非常具有實用價值,需要的朋友可以參考下2017-04-04Vue3之路由的query參數(shù)和params參數(shù)用法
這篇文章主要介紹了Vue3之路由的query參數(shù)和params參數(shù)用法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-03-03vue結合el-upload實現(xiàn)騰訊云視頻上傳功能
這篇文章主要介紹了vue結合el-upload實現(xiàn)騰訊云視頻上傳功能,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07Element樹形控件el-tree懶加載并設置默認展開和選中的效果
本文主要介紹了Element樹形控件el-tree懶加載并設置默認展開和選中的效果,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-01-01vue項目如何使用$router.go(-1)返回時刷新原來的界面
這篇文章主要介紹了vue項目如何使用$router.go(-1)返回時刷新原來的界面問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09