在 Taro Hooks 出來 以後就一直想着體驗一波 Hooks 小程序開發,不過一直忙着補番 😌。最近補完了,就搞了起來,開發了 20 天左右(其實大部分時間都在改 UI😒),基本上是完成了,而後也上架了,遂跟你們分享一點心得 😈html
能夠先掃描體驗:git
網絡不穩定的小夥伴看預覽:github
在 GitHub Pro 的開發中,我寫了四個 hooks,來幫助我複用一些重複的邏輯,提升開發效率小程序
接下來就分析一下它們的做用bash
做用同名字,用來進行網絡請求,傳入請求參數以及進行請求的函數,存儲數據,返回 [currData, refresh]
,其中currData
是存儲的返回數據,refresh
用於刷新請求。markdown
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 複製代碼
這個鉤子是最複雜的一個,也是做用最大的一個函數。可以在滾動條到底底部的時候,請求下一頁,加載更多的數據。ide
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] } 複製代碼
是否是很完美,惋惜不是這麼簡單。函數
Taro 中有個大坑就是在組件中沒法使用如usePullDownRefresh
、useReachBottom
等鉤子。oop
因此就引出來一個大問題 -- 如何在組件中觸發這些操做呢。並且在 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) } }, []) 複製代碼
其中pageReachBottomRef
、pagePullDownRef
很是關鍵,用來對消息進行配對,防止說我這個頁面滾動,致使另一個頁面也進行數據的請求。
這個鉤子用來作當下拉刷時候發送刷新頁面的消息(在 page 內使用),而接受者就前面useRequestWithMore
了
function usePullDownRefreshEvent() { const pageRef = useRef(getUniqueId()) usePullDownRefresh(() => { events.trigger(PULL_DOWN_REFRESH_EVENT, pageRef.current) }) return null } 複製代碼
這個鉤子用來作當頁面滾動到底部時候發送獲取數據的消息(在 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