這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

這樣封裝串列 hooks,一天可以開發 20 個頁面
前言
在做移動端的需求時,我們經常會開發一些串列頁,這些串列頁大多數有著相似的功能:分頁獲取串列、上拉加載、下拉重繪···
在 Vue 出來 compositionAPI 之前,我們想要復用這樣的邏輯還是比較麻煩的,好在現在 Vue2.7+都支持 compositionAPI語法了,這篇文章我將 手把手帶你用 compositionAPI 封裝一個名為 useList 的 hooks來實作串列頁的邏輯復用,
基礎版
需求分析
一個串列,最基本的需求應該包括: 發起請求,獲取到串列的陣列,然后將該陣列渲染成相應的 DOM 節點,要實作這個功能,我們需要以下變數:
- list : 陣列變數,用來存放后端回傳的資料,并在
template模板中使用v-for來遍歷渲染成我們想要的樣子, - listReq: 發起 http 請求的函式,一般是
axios的實體
代碼實作
有了上面的分析,我們可以很輕松地在 setup中寫出如下代碼:
import { ref } from 'vue'
import axios from 'axios' // 簡單示例,就不給出封裝axios的代碼了
const list = ref([])
const listReq = () => {
axios.get('/url/to/getList').then((res) => {
list.value = https://www.cnblogs.com/smileZAZ/archive/2023/01/30/res.list
})
}
listReq()
這樣,我們就完成了一個基本的串列需求的邏輯部分,大部分的串列需求都是類似的邏輯,既然如此,Don't Repeat Yourself!(不要重復寫你的代碼!),我們來把它封裝成通用的方法:
- 首先,既然是通用的,會在多個地方使用,那么資料肯定不能亂了,我們要在每次使用
useList的時候都拿到獨屬于自己的那一份資料,是不是感覺很熟悉?對的,就是以前的data為什么是一個函式那個問題!所以我們的useList是需要匯出一個函式,我們從這個函式中獲取資料與方法,讓這個函式匯出一個物件/陣列,這樣呼叫的時候解構就可以拿到我們需要的變數和方法了
// useList.js 中
const useList = () => {
// 待補充的函式體
return {}
}
export default useList
- 然后,不同的地方呼叫的介面肯定不一樣,我們想一次封裝,不再維護,那么咱們干脆在使用的時候,把呼叫介面的方法傳進來就可以了
// useList.js 中
import { ref } from 'vue'
const useList = (listReq) => {
if (!listReq) {
return new Error('請傳入介面呼叫方法!')
}
const list = ref([])
const getList = () => {
listReq().then((res) => (list.value = https://www.cnblogs.com/smileZAZ/archive/2023/01/30/res.list))
}
return {
list,
getList,
}
}
export default useList
這樣,我們就完成了一個簡單的串列 hooks,使用的時候直接:
// setup中
import useList from '@/utils'
const { list, getList } = useList(axios.get('url/to/get/list'))
getList()
等等!串列好像不涉及到 DOM操作,那咱們再偷點懶,直接在 useList內部就呼叫了吧!
// useList.js中
import { ref } from 'vue'
const useList = (listReq) => {
if (!listReq) {
return new Error('請傳入介面呼叫方法!')
}
const list = ref([])
const getList = () => {
listReq().then((res) => (list.value = https://www.cnblogs.com/smileZAZ/archive/2023/01/30/res.list))
}
getList() // 直接初始化,省去在外面初始化的步驟
return {
list,
getList,
}
}
export default useList
這時有老哥要說了,那我要是一個頁面有多個串列怎么辦?嘿嘿,別忘了,解構的時候是可以重命名的
// setup中
const { list: goodsList, getList: getGoodsList } = useList(
axios.get('/url/get/goods')
)
const { list: recommendList, getList: getRecommendList } = useList(
axios.get('/url/get/goods')
)
這樣,我們就同時在一個頁面里面,獲取到了商品串列以及推薦串列所需要的變數與方法啦
帶分頁版
如果資料量比較大的話,所有的資料全部拿出來渲染顯然不合理,所以我們一般要進行分頁處理,我們來分析一下這個需求:
需求分析
- 要分頁,那咱們肯定要告訴后端當前請求的是第幾頁、每頁多少條,可能有些地方還需要展示總共有多少條,為了方便管理,咱們把這些分頁資料統一放到
pageInfo物件中 - 分頁了,那咱們肯定還有加載下一頁的需求,需要一個
loadmore函式 - 分頁了,那咱們肯定還會有重繪的需求,需要一個
initList函式
代碼實作
需求分析好了,代碼實作起來就簡單了,廢話少說,上代碼!
// useList.js中
import { ref } from 'vue'
const useList = (listReq) => {
if (!listReq) {
return new Error('請傳入介面呼叫方法!')
}
const list = ref([])
// 新增pageInfo物件保存分頁資料
const pageInfo = ref({
pageNum: 1,
pageSize: 10,
total: 0,
})
const getList = () => {
// 分頁資料作為引數傳遞給介面呼叫函式即可
// 將請求這個Promise回傳出去,以便鏈式then
return listReq(pageInfo.value).then((res) => {
list.value = https://www.cnblogs.com/smileZAZ/archive/2023/01/30/res.list
// 更新總數量
pageInfo.value.total = res.total
// 回傳出去,交給then默認的Promise,以便后續使用
return res
})
}
// 新增加載下一頁的函式
const loadmore = () => {
// 下一頁,那咱們把當前頁自增一下就行了
pageInfo.value.pageNum += 1
// 如果已經是最后一頁了(本次獲取到空陣列)
getList().then((res) => {
if (!res.list.length) {
uni.showToast({
title:'沒有更多了',
icon: 'none',
})
}
})
}
// 新增初始化
const initList = () => {
// 初始化一般是要把所有的查詢條件都初始化,這里只有分頁,咱就回到第一頁就行
pageInfo.value.pageNum = 1
getList()
}
getList()
return {
list,
getList,
loadmore,
initList,
}
}
export default useList
完工!跑起來試試,Perfec......等等,好像不太對...
加載更多,應該是把兩次請求的資料合并到一起渲染出來才對,這怎么直接替換掉了?
回頭看看代碼,原來是咱們漏了拼接的邏輯,補上,補上
// useList.js中
// ...省略其余代碼
const getList = () => {
// 分頁資料作為引數傳遞給介面呼叫函式即可
return listReq(pageInfo.value).then((res) => {
// 當前頁不為1則是加載更多,需要拼接資料
if (pageInfo.value.pageNum === 1) {
list.value = https://www.cnblogs.com/smileZAZ/archive/2023/01/30/res.list
} else {
list.value = [...list.value, ...res.list]
}
pageInfo.value.total = res.total
return res
})
}
// ...省略其余代碼
帶 hooks 版
上面的分頁版,我們給出了 加載更多和 初始化串列功能,但是還是要手動呼叫,仔細想想,咱們重繪串列,一般都是在頁面頂部下拉的時候重繪的;而加載更多,一般都是在滾動到底部的時候加載的,既然都是一樣的觸發時機,那咱們繼續封裝吧!
需求分析
- uni-app 中提供了
onPullDownRefresh和onReachBottom鉤子,在其中處理相關邏輯即可 - 有些串列可能不是在頁面中,而是在
scroll-view中,還是需要手動處理,因此上面的函式咱們依然需要匯出
代碼實作
鉤子函式(hooks)接受一個回呼函式作為引數,咱們直接把上面的函式傳入即可
需要注意的是,uni-app 中,下拉重繪的影片需要手動關閉,咱們還需要改造一下 listReq函式
// useList中
import { onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
// ...省略其余代碼
onPullDownRefresh(initList)
onReachBottom(loadmore)
const getList = () => {
// 分頁資料作為引數傳遞給介面呼叫函式即可
return listReq(pageInfo.value)
.then((res) => {
// ...省略其余代碼
})
.finally((info) => {
// 不管成功還是失敗,關閉下拉重繪的影片
uni.stopPullDownRefresh()
// 在最后再把前面回傳的訊息return出去,以便后續處理
return info
})
}
// ...省略其余代碼
帶引數
其實在實際開發中,我們在發起請求時可能還需要其他的引數,上面我們都是固定的只有分頁的引數,可以稍加改造
需求分析
可能大家第一反應是多一個引數,或者用 展開運算子 (...)再定義一個形參就行了,這么做肯定是沒問題的,不過在這里的話不夠優雅~
我們這里是要增加一個傳給后端的引數,一般都是一起以 JSON 物件的形式傳過去,既然如此,那咱們把所有的引數都用一個物件接受,發起請求的時候和分頁引數物件合并為一個物件,代碼的可讀性會更高,使用者在使用時也可以自由地定義 key-value 鍵值對
代碼實作
// useList中
const useList = (listReq, data) => {
// ...省略其余代碼
// 判斷第二個引數是否是物件,以免后面使用展開運算子時報錯
if (data && Object.prototype.toString.call(data) !== '[object Object]') {
return new Error('額外引數請使用物件傳入')
}
const getList = () => {
const params = {
...pageInfo.value,
...data,
}
return listReq(params).then((res) => {
// ...省略其余代碼
})
}
// ...省略其余代碼
}
// ...省略其余代碼
帶默認配置版
有些時候我們的串列是在頁面中間,不需要觸底加載更多;有時候我們可能需要在不同的地方呼叫相同的介面,但是需要獲取的資料量不一樣....
為了適應各種各樣的需求,我們可以稍加改造,添加一個帶有默認值的配置物件,
// useList.js中
const defaultConfig = {
pageSize: 10, // 每頁數量,其實也可以在data里面覆寫
needLoadMore: true, // 是否需要下拉加載
data: {}, // 這個就是給介面用的額外引數了
// 還可以根據自己專案需求添加其他配置
}
// 添加一個有默認值的引數,依然滿足大部分串列頁傳入介面即可使用的需求
const useList = (listReq, config = defaultConfig) => {
// 解構的時候賦上初始值,這樣即使配置引數只傳了一個引數,也不影響其他的配置
const {
pageSize = defaultConfig.pageSize,
needLoadMore = defaultConfig.needLoadMore,
data = https://www.cnblogs.com/smileZAZ/archive/2023/01/30/defaultConfig.data,
} = config
// 應用相應的配置
if (needLoadMore) {
onReachBottom(loadmore)
}
const pageInfo = ref({
pageNum: 1,
pageSize,
total: 0,
})
// ...省略其余代碼
}
// ...省略其余代碼
這樣一來,咱們就實作了一個滿足大部分移動端串列頁的邏輯復用 hooks
web 端的幾乎只有加載更多(翻頁)的時候邏輯不太一樣,不需要拼接資料,在封裝的時候可以把分頁器的處理邏輯一起封裝進來
本文轉載于:
https://juejin.cn/post/7165467345648320520
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/542636.html
標籤:其他
上一篇:移動端 H5 實作拍照功能
