el-select自定義指令實(shí)現(xiàn)觸底加載分頁(yè)請(qǐng)求options數(shù)據(jù)(完整代碼和接口可直接用)
問(wèn)題描述
- 某些情況下,下拉框需要做觸底加載,發(fā)請(qǐng)求,獲取option的數(shù)據(jù)
- 為了方便復(fù)用,筆者封裝了一個(gè)自定義指令
- 另外也提供了一個(gè)簡(jiǎn)單的接口,用于演示
- 我們先看看效果圖
效果圖

思路分析
- 為何,不嵌入到
body標(biāo)簽中呢? - 答曰,更加方便自定義指令管理,如下屬性:
<el-select :popper-append-to-body="false" ...- 這樣的話,我們可以在自定義指令的鉤子中,可以直接使用
el.querySelector(xxx)去選中下拉框的選項(xiàng)彈出層了。就不用使用document.querySelector(xxx) - 因?yàn)?,若是嵌入?code>body層,若是同一個(gè)頁(yè)面,有多個(gè)
el-select就不太好控制管理了 - 注意下方的兩張圖,
option選項(xiàng)彈出層
不嵌入到body層

嵌入到body層

注意事項(xiàng)二
寫(xiě)一個(gè)模擬分頁(yè)函數(shù)用在express接口中
如下代碼+注釋?zhuān)?/p>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>分頁(yè)請(qǐng)求</title>
</head>
<body>
<script>
function query(pageIndex, pageSize) {
// 定義一個(gè)數(shù)組用于存放所有的模擬數(shù)據(jù)
let arr = []
// 循環(huán)追加
for (let i = 1; i < 100; i++) {
arr.push({
name: '孫悟空' + i,
age: 500 + i,
id: i
})
}
// 根據(jù)第幾頁(yè),一頁(yè)多少條來(lái)取到對(duì)應(yīng)項(xiàng)
let res = arr.slice(
(pageIndex - 1) * pageSize,
pageIndex * pageSize,
)
// 操作完畢,返回吐出來(lái),供外界使用
return res
}
console.log('第一頁(yè),要10條數(shù)據(jù):', query(1, 10));
console.log('第二頁(yè),要10條數(shù)據(jù):', query(2, 10));
</script>
</body>
</html>如下打印結(jié)果圖:

用在express接口中:
// 模擬分頁(yè)查詢(xún)
route.get('/pageData', (req, res) => {
res.header('Access-Control-Allow-Origin', '*'); // 允許跨域
let pageIndex = req.query.pageIndex // 取餐
let pageSize = req.query.pageSize // 取餐
function query(pageIndex, pageSize) {
let arr = []
for (let i = 1; i < 100; i++) {
arr.push({
name: '孫悟空' + i,
age: 500 + i,
id: i
})
}
let res = arr.slice(
(pageIndex - 1) * pageSize,
pageIndex * pageSize,
)
return res
}
res.send(query(pageIndex, pageSize)) // 返回請(qǐng)求結(jié)果
})注意事項(xiàng)三
- 注意,要按下以下的方式,進(jìn)行語(yǔ)法書(shū)寫(xiě)
- 這是一種寫(xiě)法規(guī)范,因?yàn)椋录O(jiān)聽(tīng)和解綁的句柄是一個(gè)整體
// 綁定事件,句柄handle函數(shù),要是一個(gè)整體
dom.addEventListener('scroll', handle)
// 移除事件,句柄handle函數(shù),也要對(duì)應(yīng)是一個(gè)整體
dom.removeEventListener('scroll', handle)
// 定義一個(gè)句柄函數(shù),為debounce套殼子的方式
import { debounce } from "lodash";
const handle = debounce((e) => {
// xxxxxxxx
}, 170)實(shí)現(xiàn)思路
首先給el-select添加:popper-append-to-body="false"屬性,使其在內(nèi)部管理,這樣的話,在自定義指令中的鉤子函數(shù)中,可以直接選中操作,獲取到el-option滾動(dòng)的容器
inserted(el, binding, vnode) {
let scrollWrap = el.querySelector('.el-select-dropdown .el-scrollbar .el-select-dropdown__wrap')
}- 然后,給滾動(dòng)容器綁定監(jiān)聽(tīng)事件,根據(jù)幾個(gè)高度,判斷是否觸底(最好預(yù)留幾個(gè)像素)
- 若是觸底了,就觸發(fā)外界傳遞的觸底函數(shù)執(zhí)行,這樣的話,就是通知外界繼續(xù)發(fā)請(qǐng)求,繼續(xù)獲取el-option數(shù)據(jù)
- 當(dāng)然,這里的自定義指令,要傳遞一個(gè)函數(shù)(把函數(shù)當(dāng)做參數(shù)傳遞進(jìn)來(lái),就是高階函數(shù)的思想)
- 最后,別忘了,解綁事件即可
完整代碼-自定義指令
import { debounce } from "lodash";
export default {
inserted(el, binding, vnode) {
// 獲取滾動(dòng)容器dom
let scrollWrap = el.querySelector('.el-select-dropdown .el-scrollbar .el-select-dropdown__wrap')
// 把監(jiān)聽(tīng)的句柄防抖一下
const handle = debounce((e) => {
let scrollDistance = scrollWrap.scrollHeight - scrollWrap.scrollTop
// 比如此處預(yù)留6個(gè)像素的位置用于觸底
if (scrollWrap.clientHeight + 6 > scrollDistance) {
binding.value() // 觸底通知一下,外界
}
}, 170)
// 綁定監(jiān)聽(tīng)滾動(dòng)事件
scrollWrap?.addEventListener('scroll', handle)
// 把監(jiān)聽(tīng)的句柄掛載到元素身上便于解綁時(shí)使用
el._hanlde = handle
},
unbind() {
// 獲取滾動(dòng)容器dom
let scrollWrap = el.querySelector('.el-select-dropdown .el-scrollbar .el-select-dropdown__wrap')
// 解綁
scrollWrap?.removeEventListener('scroll', el._hanlde)
// 清空
delete el._hanlde;
}
}完整代碼-給el-select使用這個(gè)自定義指令
<template>
<div class="box">
<el-select v-model="value" filterable :popper-append-to-body="false" v-down="loadmore" clearable>
<el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
options: [],
value: '',
pageIndex: 1,
pageSize: 20
};
},
mounted() {
this.getOptions()
},
methods: {
async getOptions() {
// 筆者自己的服務(wù)器,給大家提供了一個(gè)分頁(yè)接口
let url = `http://ashuai.work/api/pageData?pageIndex=${this.pageIndex}&pageSize=${this.pageSize}`
let { data } = await axios.get(url)
if (data.length == 0) return this.$message('沒(méi)數(shù)據(jù)了')
// 合并一下下拉框數(shù)據(jù)
this.options = [
...this.options,
...data
]
},
// 觸底了,繼續(xù)發(fā)請(qǐng)求
loadmore() {
this.pageIndex = this.pageIndex + 1
this.getOptions()
},
},
};
</script>項(xiàng)目演示和github倉(cāng)庫(kù)
- 為了便于大家更直觀的看效果
- 筆者把代碼推到自己的github上去了
- 并且部署到自己的服務(wù)器上了,點(diǎn)擊即看
項(xiàng)目演示網(wǎng)站:http://ashuai.work:8888/#/selectDown
項(xiàng)目github地址:https://github.com/shuirongshuifu/elementSrcCodeStudy
若是道友的項(xiàng)目中,還需要做el-select遠(yuǎn)程搜索,可以參見(jiàn)作者的這篇文章:https://segmentfault.com/a/1190000039097410
到此這篇關(guān)于el-select自定義指令實(shí)現(xiàn)觸底加載分頁(yè)請(qǐng)求options數(shù)據(jù)(附上完整代碼和接口可直接用)的文章就介紹到這了,更多相關(guān)el-select觸底分頁(yè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
uni-app之webview通信實(shí)現(xiàn)方法示例
UniApp憑借其跨平臺(tái)開(kāi)發(fā)的顯著優(yōu)勢(shì),成為眾多開(kāi)發(fā)者構(gòu)建多端應(yīng)用的首選框架,這篇文章主要介紹了uni-app之webview通信的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-07-07
Vue Element前端應(yīng)用開(kāi)發(fā)之動(dòng)態(tài)菜單和路由的關(guān)聯(lián)處理
這篇文章主要介紹了Vue Element前端應(yīng)用開(kāi)發(fā)之動(dòng)態(tài)菜單和路由的關(guān)聯(lián)處理,對(duì)vue感興趣的同學(xué),可以參考下2021-05-05
Vue 實(shí)現(xiàn)從文件中獲取文本信息的方法詳解
這篇文章主要介紹了Vue 實(shí)現(xiàn)從文件中獲取文本信息的方法,結(jié)合實(shí)例形式詳細(xì)分析了vue.js基于export導(dǎo)出的文件信息讀取相關(guān)操作技巧,需要的朋友可以參考下2019-10-10
vue3中form表單層級(jí)嵌套問(wèn)題的解決詳解
這篇文章主要為大家詳細(xì)介紹了vue3中form表單層級(jí)嵌套問(wèn)題的相關(guān)解決方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-05-05
vue+element下拉列表默認(rèn)值問(wèn)題
這篇文章主要介紹了vue+element下拉列表默認(rèn)值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06
vue2?element-ui?el-checkbox視圖不更新問(wèn)題及解決
作者在開(kāi)發(fā)過(guò)程中遇到了視圖不更新的問(wèn)題,最終通過(guò)改變一個(gè)無(wú)關(guān)緊要的響應(yīng)式數(shù)據(jù)來(lái)解決,讓視圖發(fā)生改變2024-12-12
uniapp中使用u-loadmore,loadText內(nèi)容不隨status改變刷新方式
這篇文章主要介紹了uniapp中使用u-loadmore,loadText內(nèi)容不隨status改變刷新方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05

