欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue前端框架vueuse的useScroll函數(shù)使用源碼分析

 更新時(shí)間:2022年08月18日 08:46:52   作者:NewName  
這篇文章主要為大家介紹了vueuse的useScroll函數(shù)源碼分析詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

頁(yè)面很多時(shí)候都含有可滾動(dòng)視圖區(qū)域,可能是橫向滾動(dòng)也可能是縱向滾動(dòng)。

  • 有時(shí)我們需要知道當(dāng)前的滾動(dòng)方向,是向左還是向右,是向上還是向下;
  • 有時(shí)需要知道當(dāng)前是否是正在滾動(dòng),如果滾動(dòng)則顯示一個(gè)加載動(dòng)畫(huà)等;
  • 有時(shí)我們還需要知道滾動(dòng)條是否已經(jīng)滾動(dòng)到了上下左右的邊界。

如果我們自己來(lái)實(shí)現(xiàn)這一系列的邏輯判斷可能也不難,但是如何優(yōu)雅地實(shí)現(xiàn)以便于更方便地使用呢?一起研究一下vueuse的useScroll函數(shù)吧~

1.示例

vueuse官方文檔給出了useScroll函數(shù)的demo, 我們可以在線操作看一下效果:

如上圖所示,當(dāng)向下滑動(dòng)或者拖拽豎直方向的滾動(dòng)條時(shí)則isScrolling為true表示正在向下滾動(dòng),同時(shí)useScroll能夠識(shí)別出滾動(dòng)方向?yàn)橄蛳隆?/p>

如上圖所示,當(dāng)滾動(dòng)條觸底的時(shí)候,useScroll能夠識(shí)別出已經(jīng)到達(dá)了底部。

useScroll為何如此好用,是如何實(shí)現(xiàn)的呢?我們一同學(xué)習(xí)其源碼。

2.源碼解析

先看折疊后的代碼整體了解一下:

我們發(fā)現(xiàn)整個(gè)代碼流程包括了參數(shù)的解析,狀態(tài)的定義,滾動(dòng)結(jié)束回調(diào)函數(shù),滾動(dòng)監(jiān)聽(tīng)處理函數(shù),最后是返回值,我們依次來(lái)看一下。

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接受兩個(gè)參數(shù),第一參數(shù)為目標(biāo)元素,也就是監(jiān)聽(tīng)哪一個(gè)元素的滾動(dòng)事件;第二個(gè)參數(shù)為options,涵蓋其他的選項(xiàng)。我們來(lái)詳細(xì)地看一下這些選項(xiàng)的含義:

  • throttle 滾動(dòng)事件的節(jié)流事件,默認(rèn)不對(duì)滾動(dòng)事件節(jié)流,所以throttle的默認(rèn)值為0。
  • idle 滾動(dòng)結(jié)束時(shí)的檢查事件,這個(gè)值會(huì)和throttle 加在一起對(duì)滾動(dòng)結(jié)束事件進(jìn)行防抖,分析后面的代碼時(shí)會(huì)看到
  • onStop 滾動(dòng)結(jié)束時(shí)觸發(fā)的回調(diào)函數(shù)
  • onScroll 滾動(dòng)時(shí)觸發(fā)的回調(diào)函數(shù)
  • offset 定義滾動(dòng)條到達(dá)上下左右邊界的一個(gè)偏移值,單位為像素。例如left設(shè)置為30, 則水平滾動(dòng)條距離左邊界30px時(shí)則認(rèn)為到達(dá)了左邊界。
  • eventListenerOptions 滾動(dòng)事件監(jiān)聽(tīng)器的選項(xiàng)

2.2 響應(yīng)式狀態(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,
})

定義響應(yīng)式變量x用于記錄上次滾動(dòng)的scrollLeft的值;

y記錄上次滾動(dòng)的scrollTop的值;

isScrolling表示是否正在滾動(dòng)。

arrivedState提供了水平方向滾動(dòng)條距離左邊和右邊的距離以及垂直方向滾動(dòng)條距離上邊和下邊的距離。

directions用于描述當(dāng)前滾動(dòng)的方向。

2.3 onScrollEnd滾動(dòng)結(jié)束回調(diào)

const onScrollEnd = useDebounceFn((e: Event) => {
  isScrolling.value = false
  directions.left = false
  directions.right = false
  directions.top = false
  directions.bottom = false
  onStop(e)
}, throttle + idle)

滾動(dòng)結(jié)束回調(diào)函數(shù)使用了useDebounceFn進(jìn)行防抖。當(dāng)滾動(dòng)結(jié)束后,isScrolling賦值為false, 滾動(dòng)方向全部賦值為false, 調(diào)用onStop回調(diào)。

2.4 onScrollHandler滾動(dòng)處理

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用于處理滾動(dòng)。首先是水平方向滾動(dòng)方向與是否到達(dá)左右邊界的判斷。說(shuō)明如下:

(1)獲取當(dāng)前的scrollLeft和上一次的scrollLeft也就是x.value進(jìn)行比較,如果scrollLeft < x.value說(shuō)明向左滾動(dòng),否則向右滾動(dòng)。

(2)如何判斷是否到達(dá)左邊界?這里考慮到了偏移量offset.left。如果當(dāng)前的scrollLeft <= offset.left就認(rèn)為到達(dá)了左邊界。

(3)是否到達(dá)右邊界要看當(dāng)前滾動(dòng)的距離+元素視口的寬度(clientWidth)是否大于整個(gè)內(nèi)容的寬度(scrollWidth)減去偏移量的值(offset.right)

豎直方向的判斷同理,不再贅述,如果您不熟悉clientWidth、scrollWidth的含義,您可以閱讀筆者之前的文章:scrollTop、clientHeight、 scrollHeight...學(xué)完真的理解了。

滾動(dòng)的時(shí)候還需要調(diào)用onScrollEnd觸發(fā)滾動(dòng)結(jié)束事件,調(diào)用onScroll回調(diào)函數(shù),將isScrolling設(shè)置為true。

2.5 使用 useEventListener監(jiān)聽(tīng)滾動(dòng)事件

useEventListener(
  element,
  'scroll',
  throttle ? useThrottleFn(onScrollHandler, throttle) : onScrollHandler,
  eventListenerOptions,
)

使用useEventListener監(jiān)聽(tīng)scroll事件,如果需要節(jié)流則回調(diào)函數(shù)為useThrottleFn包裝過(guò)的onScrollHandler,否則直接使用onScrollHandler。

2.6 返回值

return {
  x,
  y,
  isScrolling,
  arrivedState,
  directions,
}

useScroll最后返回響應(yīng)式狀態(tài)。我們使用一張圖總結(jié)一下這些狀態(tài):

3.總結(jié)

useScroll提供了響應(yīng)式的滾動(dòng)位置和狀態(tài)。滾動(dòng)位置包括水平方向和垂直方向的滾動(dòng)位置;滾動(dòng)狀態(tài)包括是否在滾動(dòng),是否到達(dá)了上下左右的邊界,當(dāng)前滾動(dòng)的方向。useScroll使用useEventListener來(lái)監(jiān)聽(tīng)滾動(dòng)事件,在滾動(dòng)事件的監(jiān)聽(tīng)回調(diào)函數(shù)中修改狀態(tài)和位置。在其計(jì)算位置的源碼部分我們需要了解clientWidth、scrollWidth、clientHeight、scrollHeight這些值的含義。

以上就是vueuse的useScroll函數(shù)源碼分析的詳細(xì)內(nèi)容,更多關(guān)于vueuse useScroll函數(shù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論