ElementPlus 中el-select自定義指令實(shí)現(xiàn)觸底加載請(qǐng)求options數(shù)據(jù)的方法
1) 背景:
老項(xiàng)目翻新時(shí),發(fā)現(xiàn)一個(gè)下拉框數(shù)據(jù)非常多,客戶呢,希望全部數(shù)據(jù)一起展示,意思就是全部數(shù)據(jù)一起返回給前端用于展示。但這會(huì)造成明顯的卡頓。~~明顯的不合理! QAQ!~~
于是壓力給到前端,查詢資料,各種搜索,最終找到2個(gè)解決方案。
1、在el-select下拉框中添加分頁組件,讓用戶點(diǎn)擊下一頁下一頁
2、在el-select下拉框中數(shù)據(jù),觸底加載當(dāng)然最終選擇了第二個(gè)方案,用戶體驗(yàn)會(huì)更好。
由于項(xiàng)目中有多個(gè)地方使用到 且 可能單個(gè)頁面中會(huì)用到多次,為了復(fù)用選擇了自定義指令的方式去實(shí)現(xiàn)。
2) 先來看看實(shí)現(xiàn)的效果

3) 思路
- 觸底加載,哪個(gè)元素滾動(dòng)觸底時(shí)加載?
- 承裝下拉框中所有元素的容器(.el-scrollbar__wrap)
- 觸底時(shí),觸發(fā)方法做什么?
- 觸底時(shí),繼續(xù)向后端發(fā)請(qǐng)求獲取下一頁的數(shù)據(jù),請(qǐng)求回來的數(shù)據(jù)合并給options
4) 簡單的寫一下.vue文件代碼
接口數(shù)據(jù)是自己用node寫的
后端代碼在這里:GitHub - stella99888/tao-express: Vue2+Express
```javascript
<!-- 下拉框觸底加載頁面 -->
<template>
<div class="m-4">
<p>第一個(gè)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>第二個(gè)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ā)請(qǐng)求
const loadmore = () => {
pageData.pageIndex = pageData.pageIndex + 1
getOptions()
}
</script>* 注意一下:
1. teleported屬性為官網(wǎng)提供,是否將下拉列表插入至 body 元素,默認(rèn)值為true,插入到body元素中。
> 這是插入body中的

> 這是不插入body中的(可以對(duì)比下)

2. 我們需要將其插入body元素中嗎?如果是單個(gè)頁面中只出現(xiàn)一個(gè),那影響不大;如果是多個(gè),我們要選中該元素時(shí)就很不方便了。
3. 且,我們這邊使用的是自定義指令的方式,指令在el-select元素上,teleported為false,不插入body時(shí),正好可以在自定義指令中使用el.querySelector('.el-scrollbar__wrap')獲取滾動(dòng)的元素。
5) 自定義指令
前端代碼在這里:GitHub - wwaini/tao-vue3 at release240625
// src/directives/loadmore/index.js
import { debounce } from "lodash";
export default {
mounted(el, binding) {
// 不插入body時(shí),以下方式可獲取元素
// 插入body時(shí),需要以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個(gè)像素的位置用于觸底
if (scrollWrap.clientHeight + 10 > scrollDistance) {
binding.value() // 觸底通知一下,外界
}
}, 170)
// 綁定監(jiān)聽滾動(dòng)事件
scrollWrap?.addEventListener('scroll', handle)
// 方法掛載到元素身上便于解綁時(shí)使用
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"
// 自定義指令對(duì)象,用于遍歷注冊(cè)
const directives = {
loadmore
}
// 批量注冊(cè)指令并暴露到main.js中去便于注冊(cè)
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>第一個(gè)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>第二個(gè)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ā)請(qǐng)求
const loadmore = () => {
pageData.pageIndex = pageData.pageIndex + 1
getOptions()
}
</script>到此這篇關(guān)于ElementPlus 中el-select自定義指令實(shí)現(xiàn)觸底加載請(qǐng)求options數(shù)據(jù)的文章就介紹到這了,更多相關(guān)el-select觸底加載請(qǐng)求options數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用proxy實(shí)現(xiàn)一個(gè)更優(yōu)雅的vue【推薦】
Proxy 用于修改某些操作的默認(rèn)行為,等同于在語言層面做出修改,所以屬于一種“元編程”。這篇文章主要介紹了用proxy實(shí)現(xiàn)一個(gè)更優(yōu)雅的vue,需要的朋友可以參考下2018-06-06
vue數(shù)據(jù)更新但視圖(DOM)不刷新的幾種解決辦法
這篇文章主要給大家介紹了關(guān)于vue數(shù)據(jù)更新但視圖(DOM)不刷新的幾種解決辦法,我們?cè)陂_發(fā)過程中經(jīng)常會(huì)碰到數(shù)據(jù)更新,但是視圖并未改變的情況,需要的朋友可以參考下2023-08-08
vue深拷貝的3種實(shí)現(xiàn)方式小結(jié)
當(dāng)使用同一個(gè)對(duì)象產(chǎn)生沖突時(shí),可以使用lodash包,對(duì)該對(duì)象進(jìn)行深拷貝,從而使操作的對(duì)象為不同的對(duì)象,這篇文章主要給大家介紹了關(guān)于vue深拷貝的3種實(shí)現(xiàn)方式,需要的朋友可以參考下2023-02-02
使用vue構(gòu)建移動(dòng)應(yīng)用實(shí)戰(zhàn)代碼
本篇文章主要介紹了使用vue構(gòu)建移動(dòng)應(yīng)用實(shí)戰(zhàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08
vue-router的導(dǎo)航守衛(wèi)使用最新講解
這篇文章主要介紹了vue-router的導(dǎo)航守衛(wèi)使用講解,vue-router提供了許多編程式導(dǎo)航的API,其中最常見的導(dǎo)航API有很多種,本文給大家詳細(xì)講解,需要的朋友可以參考下2022-12-12
Vue+ElementUI?實(shí)現(xiàn)分頁功能-mysql數(shù)據(jù)
這篇文章主要介紹了Vue+ElementUI?實(shí)現(xiàn)分頁查詢-mysql數(shù)據(jù),當(dāng)數(shù)據(jù)庫中數(shù)據(jù)比較多時(shí),就每次只查詢一部分來緩解服務(wù)器和頁面壓力。這里使用elementui的?Pagination?分頁?組件,配合mysql的limit語句,實(shí)現(xiàn)分頁查詢mysql數(shù)據(jù),下面來看看具體實(shí)現(xiàn)過程,希望對(duì)大家學(xué)習(xí)有所幫助2021-12-12
使用vue.js實(shí)現(xiàn)checkbox的全選和多個(gè)的刪除功能
這篇文章主要介紹了使用vue.js實(shí)現(xiàn)checkbox的全選和多個(gè)的刪除功能,需要的朋友可以參考下2017-02-02

