ElSelect二次封裝組件實現(xiàn)分頁(下拉加載、緩存)、回顯功能實例
前言
一個基于 Vue 3 + Element Plus 的 <el-select> 封裝組件:支持遠程搜索、分頁加載(無限加載/觸底加載)、可選緩存與可選回顯(detailApi),適合“遠程大數(shù)據(jù)下拉選擇”的場景。
1. 安裝
npm i select-pagination-element-plus
2. 快速開始(最小可用)
下面示例展示最基本用法:輸入關鍵詞 → 遠程查詢 → 下拉觸底繼續(xù)加載。
<template>
<SelectPagination v-model="value" :api="fetchUsers" placeholder="輸入關鍵詞搜索" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import SelectPagination from 'select-pagination-element-plus'
const value = ref('')
const fetchUsers = async (params: any) => {
// params 內(nèi)默認會包含:page、size、name(可配置)
// 你也可以通過組件 props.params 傳額外查詢參數(shù)
// 約定返回結構:默認 responsePath = "data.data"
// responsePath 指向的對象必須包含:
// - content: 選項數(shù)組
// - totalElements: 總數(shù)量
return {
data: {
data: {
content: [
{ id: 'u-1', label: '用戶 1', value: 'u-1' },
{ id: 'u-2', label: '用戶 2', value: 'u-2' }
],
totalElements: 2
}
}
}
}
</script>
3. 后端返回結構(responsePath)
組件會通過 responsePath 在響應對象中定位分頁數(shù)據(jù),默認:
responsePath = "data.data"
該路徑最終需要指向一個對象,且至少包含:
{
content: any[]
totalElements: number
}3.1 示例:后端返回是{ data: { list, total } }
你可以這么配置:
<SelectPagination v-model="value" :api="fetchUsers" response-path="data" />
并確保 fetchUsers 返回里 data 對象包含 content/totalElements,或者你在 fetchUsers 內(nèi)轉換成統(tǒng)一結構。
4. 參數(shù)說明(Props 字段含義)
4.1 數(shù)據(jù)與行為
| 參數(shù) | 類型 | 默認值 | 含義(建議閱讀) |
|---|---|---|---|
| modelValue | string | number | any[] | '' | v-model 值,單選為標量,多選為數(shù)組 |
| isRemote | boolean | true | 是否啟用 Element Plus 的 remote 模式;為 true 時會走遠程搜索邏輯 |
| api | (params) => Promise<any> | any 或 () => (params) => Promise<any> | any | - | 拉取分頁列表的函數(shù)(見第 5 節(jié)) |
| apiAsync | boolean | false | 為 true 時,api 被視為“工廠函數(shù)”,會 await api() 得到真正的請求函數(shù) |
| params | object | () => object | {} | 每次請求都會合并的額外參數(shù);用函數(shù)可動態(tài)生成(比如依賴外部響應式條件) |
| initOptions | any[] | [] | 初始選項(常用于預置、默認項、或者本地固定項),會合并進 options |
4.2 字段映射(label/value)
| 參數(shù) | 類型 | 默認值 | 含義 |
|---|---|---|---|
| labelField | string | 'label' | option 顯示文本字段名 |
| valueField | string | 'value' | option 實際值字段名 |
例如你的后端返回 [{ userId, userName }],可以:
<SelectPagination v-model="value" :api="fetchUsers" label-field="userName" value-field="userId" />
4.3 分頁與搜索參數(shù)(發(fā)給后端的字段名)
| 參數(shù) | 類型 | 默認值 | 含義 |
|---|---|---|---|
| pageSize | number | 10 | 每頁數(shù)量 |
| pageKey | string | 'page' | 頁碼字段名(發(fā)給后端的 key) |
| sizeKey | string | 'size' | 每頁大小字段名 |
| keyword | string | 'name' | 搜索關鍵詞字段名(也就是 query 的 key) |
舉例:默認請求參數(shù)類似:
{
page: 1,
size: 10,
name: "張"
}如果你的后端是 current/limit/keyword:
<SelectPagination v-model="value" :api="fetchUsers" page-key="current" size-key="limit" keyword="keyword" />
4.4 響應路徑
| 參數(shù) | 類型 | 默認值 | 含義 |
|---|---|---|---|
| responsePath | string | 'data.data' | 用點號路徑從響應中取分頁對象(見第 3 節(jié)) |
4.5 緩存(提高體驗,減少重復請求)
| 參數(shù) | 類型 | 默認值 | 含義 |
|---|---|---|---|
| enableCache | boolean | true | 是否緩存:已加載 options、頁碼、關鍵詞等 |
| cacheKey | string | '' | 緩存命名空間;為空時內(nèi)部會用 api.name + params 生成一個 key |
緩存適用場景:下拉多次分頁加載后關閉再打開,希望還停留在上次加載的結果與位置。
4.6 回顯與詳情(detailApi / changeDetail)
| 參數(shù) | 類型 | 默認值 | 含義 |
|---|---|---|---|
| changeDetail | boolean | false | 為 true 時,選中后會額外觸發(fā) change-detail 事件,把選中項的 option 數(shù)據(jù)回傳 |
| detailApi | (value) => Promise<any> | any | null | 用于“回顯”:當 modelValue 有值但 options 里沒有對應項時,用 value 拉取詳情并插入 options |
典型場景:表單編輯頁從后端拿到 userId,但下拉列表還沒加載;此時通過 detailApi(userId) 把該用戶詳情拉回來做回顯。
4.7 樣式與觸底哨兵
| 參數(shù) | 類型 | 默認值 | 含義 |
|---|---|---|---|
| popperClass | string | '' | 額外傳給 el-select 的 popper-class,用于定制下拉面板樣式作用域 |
| footerSentinelId | string | '' | 自定義 footer sentinel 的 DOM id;內(nèi)部用它定位觸底觀察點(一般不需要傳) |
5. api 的寫法(最重要)
組件會在這些時機調用 api(params):
- 下拉打開且無緩存(或緩存為空)時
- 輸入關鍵詞觸發(fā)遠程搜索時
- 觸底(或點擊“加載更多”)時拉取下一頁
5.1 api(params) 直接是請求函數(shù)
const api = async (params: any) => {
return request.get('/users', { params })
}
5.2 apiAsync = true:api 先返回請求函數(shù)(適合依賴異步初始化)
<SelectPagination v-model="value" :api="createApi" :api-async="true" />
const createApi = async () => {
const token = await getTokenSomehow()
return (params: any) => request.get('/users', { params, headers: { token } })
}
6. 事件(Events)
| 事件名 | 參數(shù) | 說明 |
|---|---|---|
| update:modelValue | any | v-model 更新 |
| change | any | 同 Element Plus 的 change |
| change-detail | any | any[] | null | 當 changeDetail = true 時返回選中項詳情(單選返回對象,多選返回數(shù)組) |
7. 插槽(Slots)
7.1 footer:完全自定義“加載中/沒有更多/加載更多”
slot props:
loading:boolean當前是否在請求hasMore:boolean是否還有下一頁options:any[]當前已加載的 optionsloadMore:() => void主動觸發(fā)加載更多
示例:
<SelectPagination v-model="value" :api="fetchUsers" footer-sentinel-id="user-select-footer">
<template #footer="{ loading, hasMore, loadMore }">
<div v-if="loading" style="padding: 8px 0; text-align: center">加載中...</div>
<div v-else-if="!hasMore" style="padding: 8px 0; text-align: center">沒有更多了</div>
<div v-else style="padding: 8px 0; text-align: center; cursor: pointer" @click="loadMore">
點擊加載更多
</div>
</template>
</SelectPagination>8. 暴露方法(ref)
通過組件 ref 訪問:
loadData(isReset?: boolean):加載數(shù)據(jù),傳true表示重置并從第一頁開始clearCache():清除緩存restoreCache():手動恢復緩存(返回是否成功)updateValue(val):手動更新值(會觸發(fā) v-model/change)loadEchoData():手動觸發(fā)回顯數(shù)據(jù)拉取setPage(page: number):設置頁碼(一般調試用)setOptions(options: any[]):直接覆蓋 options(一般調試用)options:當前 options 的 refcurrentPage:當前頁碼的 ref
總結
到此這篇關于ElSelect二次封裝組件實現(xiàn)分頁(下拉加載、緩存)、回顯功能的文章就介紹到這了,更多相關ElSelect二次封裝組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Vue3實現(xiàn)Element Plus表格的多選功能與條件操作
Element-plus是ElementUI的升級版,是一套基于vue2與vue3的桌面端組件庫,它提供了豐富的組件幫助開發(fā)人員快速構建功能強大、風格統(tǒng)一的頁面,本文給大家介紹了Vue3實現(xiàn)Element Plus表格的多選功能與條件操作,需要的朋友可以參考下2024-08-08
一文搞明白vue開發(fā)者vite多環(huán)境配置
Vue是一款流行的JavaScript框架,用于開發(fā)動態(tài)單頁應用程序,本地安裝和環(huán)境配置是學習和使用Vue的第一步,下面這篇文章主要給大家介紹了關于vue開發(fā)者vite多環(huán)境配置的相關資料,需要的朋友可以參考下2023-06-06
解決使用vue-awesome-swiper組件手動滾動點擊失效問題
這篇文章主要介紹了使用vue-awesome-swiper組件手動滾動點擊失效問題解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06

