使用 Taro Hooks 快速開發一個小程序-- GitHub Pro

在 Taro Hooks 出來 以後就一直想着體驗一波 Hooks 小程序開發,不過一直忙着補番 😌。最近補完了,就搞了起來,開發了 20 天左右(其實大部分時間都在改 UI😒),基本上是完成了,而後也上架了,遂跟你們分享一點心得 😈html

能夠先掃描體驗:git

網絡不穩定的小夥伴看預覽:github

在 GitHub Pro 的開發中,我寫了四個 hooks,來幫助我複用一些重複的邏輯,提升開發效率小程序

  • useRequest
  • useRequestWithMore
  • useReachBottomEvent
  • usePullDownRefreshEvent

接下來就分析一下它們的做用bash

useRequest

做用同名字,用來進行網絡請求,傳入請求參數以及進行請求的函數,存儲數據,返回 [currData, refresh] ,其中currData是存儲的返回數據,refresh用於刷新請求。網絡

function useRequest<T>(
  params: any,
  request: (params: any) => Promise<T | null>
): [T | null, () => void] | [] {
  const [currData, setData] = useState<T | null>(null)
  const [count, setCount] = useState(0)
  const pagePullDownRef = useRef('')

  useEffect(() => {
    request(params).then(data => {
      if (data) {
        setData(data)
      }
    })
  }, [count])

  usePullDownRefresh(() => {
    refresh()
  })

  useEffect(() => {
    events.on(PULL_DOWN_REFRESH_EVENT, (page: string) => {
      if (!pagePullDownRef.current) {
        pagePullDownRef.current = page
      } else if (pagePullDownRef.current !== page) {
        return
      }
      refresh()
    })
    return () => {
      events.off(PULL_DOWN_REFRESH_EVENT)
    }
  }, [])

  const refresh = () => {
    setCount(count + 1)
  }

  return [currData, refresh]
}

export default useRequest
複製代碼

useRequestide

useRequestWithMore

這個鉤子是最複雜的一個,也是做用最大的一個函數。可以在滾動條到底底部的時候,請求下一頁,加載更多的數據。函數

function useRequestWIthMore<T, S = string>(
  data: S,
  request: (data: S, params: any | null) => Promise<T[] | null>
): [T[] | null, boolean, () => void, () => void] | [] {
  if (!data) {
    // bug?
    console.warn('useRequestWIthMore: no data')
    return []
  }

  const [currData, setData] = useState<T[] | null>(null)
  const [hasMore, setHasMore] = useState<boolean>(true)
  const [params, setParams] = useState(defaultParams)
  const loadingRef = useRef(false)

  useEffect(() => {
    if (hasMore) {
      loadingRef.current = true
      request(data, params)
        .then(data => {
          if (data) {
            if (currData) {
              setData([...currData, ...data])
            } else {
              setData(data)
            }
            if (data.length < params.per_page!) {
              setHasMore(false)
            }
          }
        })
        .finally(() => {
          loadingRef.current = false
          Taro.stopPullDownRefresh()
          Taro.hideLoading()
        })
    }
  }, [params])

  usePullDownRefresh(() => {
    refresh()
  })

  useReachBottom(() => {
    if (loadingRef.current) {
      return
    }
    getMoreData()
  })

  const getMoreData = () => {
    setParams(params => ({ ...params, page: params.page! + 1 }))
  }

  const refresh = () => {
    setData(null)
    setHasMore(true)
    setParams({ ...params, page: 1 })
  }

  return [currData, hasMore, refresh, getMoreData]
}
複製代碼

是否是很完美,惋惜不是這麼簡單。ui

Taro 中有個大坑就是在組件中沒法使用如usePullDownRefreshuseReachBottom等鉤子。spa

因此就引出來一個大問題 -- 如何在組件中觸發這些操做呢。並且在 GitHub Pro 中,我把不少組件進行了拆分,難道我要重寫?😑

這確定是不行的。還好貼心的 Taro 給咱們提供了一個消息機制(實際上就是發佈訂閱),能夠用它來解決咱們當前遇到的問題。

// 存儲惟一 id 用於匹配消息
  const pageReachBottomRef = useRef('')
  const pagePullDownRef = useRef('')

  useEffect(() => {
    events.on(REACH_BOTTOM_EVENT, (page: string) => {
      if (loadingRef.current) {
        return
      }
      if (!pageReachBottomRef.current) {
        pageReachBottomRef.current = page
      } else if (pageReachBottomRef.current !== page) {
        return
      }
      getMoreData()
    })
    return () => {
      events.off(REACH_BOTTOM_EVENT)
    }
  }, [])

  useEffect(() => {
    events.on(PULL_DOWN_REFRESH_EVENT, (page: string) => {
      if (!pagePullDownRef.current) {
        pagePullDownRef.current = page
      } else if (pagePullDownRef.current !== page) {
        return
      }
      refresh()
    })
    return () => {
      events.off(PULL_DOWN_REFRESH_EVENT)
    }
  }, [])
複製代碼

其中pageReachBottomRefpagePullDownRef很是關鍵,用來對消息進行配對,防止說我這個頁面滾動,致使另一個頁面也進行數據的請求。

useRequestWIthMore

usePullDownRefreshEvent

這個鉤子用來作當下拉刷時候發送刷新頁面的消息(在 page 內使用),而接受者就前面useRequestWithMore

function usePullDownRefreshEvent() {
  const pageRef = useRef(getUniqueId())
  usePullDownRefresh(() => {
    events.trigger(PULL_DOWN_REFRESH_EVENT, pageRef.current)
  })

  return null
}
複製代碼

usePullDownRefreshEvent

useReachBottomEvent

這個鉤子用來作當頁面滾動到底部時候發送獲取數據的消息(在 page 內使用),而接受者就前面useRequestWithMore了,而且我在內部作了一下節流。

function useReachBottomEvent() {
  const pageRef = useRef(getUniqueId())
  const timerRef = useRef(0)

  useReachBottom(() => {
    const prev = timerRef.current
    const curr = +Date.now()
    if (!prev || curr - prev > THROTTLE_DELAY) {
      events.trigger(REACH_BOTTOM_EVENT, pageRef.current)
      timerRef.current = curr
    } else {
      console.log('wait...')
    }
  })

  return null
}
複製代碼

總結

在 GitHub Pro 開發中,使用 Hooks 可以提升邏輯的複用,大大加快開發的速度,目前我尚未遇到過什麼大坑,因此開發體驗仍是不錯的。

推薦資料:

以上我主要講了如何寫 Hooks,而編寫以後的使用,能夠自行看項目的代碼

Repo: zenghongtu/GitHub-Pro

相關文章
相關標籤/搜索