ElementPlus 中el-select自定義指令實(shí)現(xiàn)觸底加載請求options數(shù)據(jù)的方法
1) 背景:
老項目翻新時,發(fā)現(xiàn)一個下拉框數(shù)據(jù)非常多,客戶呢,希望全部數(shù)據(jù)一起展示,意思就是全部數(shù)據(jù)一起返回給前端用于展示。但這會造成明顯的卡頓。~~明顯的不合理! QAQ!~~
于是壓力給到前端,查詢資料,各種搜索,最終找到2個解決方案。
1、在el-select下拉框中添加分頁組件,讓用戶點(diǎn)擊下一頁下一頁
2、在el-select下拉框中數(shù)據(jù),觸底加載當(dāng)然最終選擇了第二個方案,用戶體驗會更好。
由于項目中有多個地方使用到 且 可能單個頁面中會用到多次,為了復(fù)用選擇了自定義指令的方式去實(shí)現(xiàn)。
2) 先來看看實(shí)現(xiàn)的效果
3) 思路
- 觸底加載,哪個元素滾動觸底時加載?
- 承裝下拉框中所有元素的容器(.el-scrollbar__wrap)
- 觸底時,觸發(fā)方法做什么?
- 觸底時,繼續(xù)向后端發(fā)請求獲取下一頁的數(shù)據(jù),請求回來的數(shù)據(jù)合并給options
4) 簡單的寫一下.vue文件代碼
接口數(shù)據(jù)是自己用node寫的
后端代碼在這里:GitHub - stella99888/tao-express: Vue2+Express
```javascript <!-- 下拉框觸底加載頁面 --> <template> <div class="m-4"> <p>第一個select</p> <el-select v-model="value" v-loadmore="loadmore" :teleported="false" style="width:240px"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <p>第二個select</p> <el-select v-model="value" v-loadmore="loadmore" :teleported="false" style="width:240px"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </div> </template> <script setup> import axios from 'axios'; import { onMounted, reactive, ref } from 'vue' const list = ref([]) const options = ref([]) const option = ref([]) const value = ref([]) const loading = ref(false) let pageData = reactive({ pageIndex: 1, pageSize: 10 }) onMounted(() => { getOptions() }) const getOptions = () => { axios.get(`http://localhost:9999/getSelectOptions?pageIndex=${pageData.pageIndex}&pageSize=${pageData.pageSize}`) .then(res => { console.log(res.data); if (res.data.length < 1) { ElMessage({ message: '沒有更多數(shù)據(jù)了...', type: "warning", }); } const newOptions = res.data.map((item) => { return { value: item.name, label: item.index } }) options.value.push(...newOptions) }) } // 觸底了,繼續(xù)發(fā)請求 const loadmore = () => { pageData.pageIndex = pageData.pageIndex + 1 getOptions() } </script>
* 注意一下:
1. teleported屬性為官網(wǎng)提供,是否將下拉列表插入至 body 元素,默認(rèn)值為true,插入到body元素中。
> 這是插入body中的
> 這是不插入body中的(可以對比下)
2. 我們需要將其插入body元素中嗎?如果是單個頁面中只出現(xiàn)一個,那影響不大;如果是多個,我們要選中該元素時就很不方便了。
3. 且,我們這邊使用的是自定義指令的方式,指令在el-select元素上,teleported為false,不插入body時,正好可以在自定義指令中使用el.querySelector('.el-scrollbar__wrap')獲取滾動的元素。
5) 自定義指令
前端代碼在這里:GitHub - wwaini/tao-vue3 at release240625
// src/directives/loadmore/index.js import { debounce } from "lodash"; export default { mounted(el, binding) { // 不插入body時,以下方式可獲取元素 // 插入body時,需要以document.querySelector('.el-scrollbar__wrap')獲取 let scrollWrap = el.querySelector('.el-scrollbar__wrap') // 把監(jiān)聽的方法防抖一下 const handle = debounce((e) => { let scrollDistance = scrollWrap.scrollHeight - scrollWrap.scrollTop // 比如此處預(yù)留10個像素的位置用于觸底 if (scrollWrap.clientHeight + 10 > scrollDistance) { binding.value() // 觸底通知一下,外界 } }, 170) // 綁定監(jiān)聽滾動事件 scrollWrap?.addEventListener('scroll', handle) // 方法掛載到元素身上便于解綁時使用 el._hanlde = handle }, unmounted(el, binding) { let scrollWrap = document.querySelector('.el-scrollbar__wrap') scrollWrap?.removeEventListener('scroll', el._hanlde) el._hanlde = null } }
// directives/index.js import loadmore from "./loadmore" // 自定義指令對象,用于遍歷注冊 const directives = { loadmore } // 批量注冊指令并暴露到main.js中去便于注冊 export default { install(app) { Object.keys(directives).forEach((key) => { app.directive(key, directives[key]) }) } }
// main.js import { createApp } from 'vue'; import App from './App.vue'; const app = createApp(App); // 引入并使用自定義指令 import directive from './directives' app.use(directive); app.mount('#app');
// src/views/num/six.vue <!-- 下拉框觸底加載自定義指令 --> <template> <div class="m-4"> <p>第一個select</p> <el-select v-model="value" v-loadmore="loadmore" :teleported="false" style="width:240px"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <p>第二個select</p> <el-select v-model="value" v-loadmore="loadmore" :teleported="false" style="width:240px"> <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </div> </template> <script setup> import axios from 'axios'; import { onMounted, reactive, ref } from 'vue' const list = ref([]) const options = ref([]) const option = ref([]) const value = ref([]) const loading = ref(false) let pageData = reactive({ pageIndex: 1, pageSize: 10 }) onMounted(() => { getOptions() }) const getOptions = () => { axios.get(`http://localhost:9999/getSelectOptions?pageIndex=${pageData.pageIndex}&pageSize=${pageData.pageSize}`) .then(res => { console.log(res.data); if (res.data.length < 1) { ElMessage({ message: '沒有更多數(shù)據(jù)了...', type: "warning", }); } const newOptions = res.data.map((item) => { return { value: item.name, label: item.index } }) options.value.push(...newOptions) }) } // 觸底了,繼續(xù)發(fā)請求 const loadmore = () => { pageData.pageIndex = pageData.pageIndex + 1 getOptions() } </script>
到此這篇關(guān)于ElementPlus 中el-select自定義指令實(shí)現(xiàn)觸底加載請求options數(shù)據(jù)的文章就介紹到這了,更多相關(guān)el-select觸底加載請求options數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用proxy實(shí)現(xiàn)一個更優(yōu)雅的vue【推薦】
Proxy 用于修改某些操作的默認(rèn)行為,等同于在語言層面做出修改,所以屬于一種“元編程”。這篇文章主要介紹了用proxy實(shí)現(xiàn)一個更優(yōu)雅的vue,需要的朋友可以參考下2018-06-06vue數(shù)據(jù)更新但視圖(DOM)不刷新的幾種解決辦法
這篇文章主要給大家介紹了關(guān)于vue數(shù)據(jù)更新但視圖(DOM)不刷新的幾種解決辦法,我們在開發(fā)過程中經(jīng)常會碰到數(shù)據(jù)更新,但是視圖并未改變的情況,需要的朋友可以參考下2023-08-08vue深拷貝的3種實(shí)現(xiàn)方式小結(jié)
當(dāng)使用同一個對象產(chǎn)生沖突時,可以使用lodash包,對該對象進(jìn)行深拷貝,從而使操作的對象為不同的對象,這篇文章主要給大家介紹了關(guān)于vue深拷貝的3種實(shí)現(xiàn)方式,需要的朋友可以參考下2023-02-02使用vue構(gòu)建移動應(yīng)用實(shí)戰(zhàn)代碼
本篇文章主要介紹了使用vue構(gòu)建移動應(yīng)用實(shí)戰(zhàn)代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08vue-router的導(dǎo)航守衛(wèi)使用最新講解
這篇文章主要介紹了vue-router的導(dǎo)航守衛(wèi)使用講解,vue-router提供了許多編程式導(dǎo)航的API,其中最常見的導(dǎo)航API有很多種,本文給大家詳細(xì)講解,需要的朋友可以參考下2022-12-12Vue+ElementUI?實(shí)現(xiàn)分頁功能-mysql數(shù)據(jù)
這篇文章主要介紹了Vue+ElementUI?實(shí)現(xiàn)分頁查詢-mysql數(shù)據(jù),當(dāng)數(shù)據(jù)庫中數(shù)據(jù)比較多時,就每次只查詢一部分來緩解服務(wù)器和頁面壓力。這里使用elementui的?Pagination?分頁?組件,配合mysql的limit語句,實(shí)現(xiàn)分頁查詢mysql數(shù)據(jù),下面來看看具體實(shí)現(xiàn)過程,希望對大家學(xué)習(xí)有所幫助2021-12-12使用vue.js實(shí)現(xiàn)checkbox的全選和多個的刪除功能
這篇文章主要介紹了使用vue.js實(shí)現(xiàn)checkbox的全選和多個的刪除功能,需要的朋友可以參考下2017-02-02