iT邦幫忙

2024 iThome 鐵人賽

DAY 10
1
JavaScript

不會 VueUse 而被提分手的我系列 第 10

D-10 useCycleList 解析與動機 — 解析循環的齒輪

  • 分享至 

  • xImage
  •  

深入了解了 useCycleList。它就像機械中的齒輪,每次轉動都精密而有規律。每一個元素的切換,就像齒輪不斷運轉,讓系統持續運行,永無停歇。在這無限的循環中,我看到了穩定與持續的力量。這不僅是我學習的象徵,更像是我和程世社季子之間的關係,不論經歷多少次轉折,都會回到起點,重新開始。循環或許不會有終點,但每次轉動都帶來成長與變化。程世社季子,等著我,我會用這永不停止的力量讓我們的故事延續下去。
#挽回愛情的第十天
https://ithelp.ithome.com.tw/upload/images/20240923/20162115C6LIvlkisz.png

本篇筆者將重點放在 useCycleList 的原始碼解析,讓各位更進一步了解 VueUse 中這個實用的組合式函式。

1. 型別定義

export interface UseCycleListOptions<T> {
  initialValue?: MaybeRef<T>
  fallbackIndex?: number
  getIndexOf?: (value: T, list: T[]) => number
}

export interface UseCycleListReturn<T> {
  state: Ref<T>
  index: Ref<number>
  next: (n?: number) => T
  prev: (n?: number) => T
  go: (i: number) => T
}

這裡定義了兩個介面:

  • UseCycleListOptions<T>: 定義了 useCycleList 的選項。
  • UseCycleListReturn<T>: 定義了 useCycleList 返回的物件結構。

2. useCycleList 函式

export function useCycleList<T>(
  list: MaybeRefOrGetter<T[]>,
  options?: UseCycleListOptions<T>
): UseCycleListReturn<T> {
  const state = shallowRef(getInitialValue()) as Ref<T>
  const listRef = toRef(list)
  // ... 其餘程式碼
}

useCycleList 函式接受兩個參數:

  • list: 要循環的列表,可以是一個陣列、ref 或 getter 函式。
  • options: 可選的配置選項。

3. 索引計算

const index = computed<number>({
  get() {
    const targetList = listRef.value
    let index = options?.getIndexOf
      ? options.getIndexOf(state.value, targetList)
      : targetList.indexOf(state.value)
    if (index < 0)
      index = options?.fallbackIndex ?? 0
    return index
  },
  set(v) {
    set(v)
  },
})

這個 computed 屬性計算當前項目在列表中的索引:

  • 如果提供了 getIndexOf 函式,則使用它來獲取索引。
  • 否則,使用 indexOf 方法。
  • 如果索引小於 0,則使用 fallbackIndex 或 0。

4. 核心邏輯函式

function set(i: number) {
  const targetList = listRef.value
  const length = targetList.length
  const index = (i % length + length) % length
  const value = targetList[index]
  state.value = value
  return value
}

function shift(delta = 1) {
  return set(index.value + delta)
}

function next(n = 1) {
  return shift(n)
}

function prev(n = 1) {
  return shift(-n)
}

這些函式實現了循環列表的核心邏輯:

  • set: 設置指定索引的值,處理循環邏輯。
  • shift: 移動指定步數。
  • nextprev: 基於 shift 實現向前和向後移動。

5. 初始值獲取

function getInitialValue() {
  return toValue(options?.initialValue ?? toValue<T[]>(list)[0]) ?? undefined
}

這個函式用於獲取初始值,優先使用 options 中的 initialValue,如果沒有則使用列表的第一個元素。

6. 監聽列表變化

watch(listRef, () => set(index.value))

這行程式碼監聽列表的變化,當列表變化時,重新設置當前索引的值。

7. 返回值

return {
  state,
  index,
  next,
  prev,
  go: set,
}

函式最後返回一個物件,包含了狀態、索引以及操作函式。

總結

useCycleList 的實現巧妙地利用了 Vue 的響應式系統和 computed 屬性。它不僅實現了基本的循環列表功能,還提供了靈活的配置選項,如自定義索引查找函式和回退索引。

這個組合式函式展示了如何將複雜的邏輯封裝成簡單易用的 API,同時保持了良好的彈性和可擴展性。它運用了 TypeScript 的泛型來確保類型安全,並利用了 Vue 3 的 composition API 來構建響應式的資料流。

通過學習 useCycleList 的實現,開發者可以深入理解 VueUse 的設計理念和實現技巧,這對於提升 Vue 應用開發技能非常有幫助。


上一篇
D-09 useCycleList 文件說明與範例 — 循環的藝術
下一篇
D-11 用 useCycleList 來做一個簡單的輪播吧 (carousel) — 從需求分析到未來優化
系列文
不會 VueUse 而被提分手的我30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言