最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue3 el-select懶加載以及自定義指令方式

 更新時(shí)間:2024年04月25日 09:25:50   作者:偷只貓來(lái)養(yǎng)  
這篇文章主要介紹了vue3 el-select懶加載以及自定義指令方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

vue3 el-select懶加載以及自定義指令

要求:自定義搜索、自定義指令,滾動(dòng)懶加載每次展示10條數(shù)據(jù)

在element-plus中,el-select的選項(xiàng)框是使用popper.js生成的,不在body中,無(wú)法直接獲取,這時(shí)需要巧妙地使用popper-class屬性來(lái)獲取到dom并掛載到el-select進(jìn)行監(jiān)聽(tīng)來(lái)實(shí)現(xiàn)我們的需求。

下面是代碼:

<template>
    <el-select 
        v-model="value"
        :loading="loading"
        loading-text="數(shù)據(jù)加載中..." 
        filterable
        clearable
        popper-class="event-select-poper"
        v-el-select-loadmore="loadmore"
        :placeholder="placeholder"
        style="width: 100%"
        :filter-method="filterOptions"
        @change="handleEventsChange"
        @visible-change="handleVisibleChange">
        <el-option
            v-for="(item, index) in options"
            :key="index"
            :label="item.eventTheme"
            :value="item.logCode">
        </el-option>
    </el-select>
</template>

在vue3的setup語(yǔ)法糖中,以v開(kāi)頭的變量會(huì)被識(shí)別為指令,一般指令變量命名使用小駝峰語(yǔ)法

<script setup>
import { ref, reactive, watch, nextTick, onBeforeMount } from 'vue'

const props = defineProps({
    eventId: {
        type: [String, Number],
        default: ''
    },
    placeholder: {
        type: String,
        default: ''
    }
})

const emits = defineEmits(['change'])

let options = reactive([])
let loading = ref(false)
let value = ref('')
let allEvents = reactive([
    { eventTheme: '1', logCode: 1 },
    { eventTheme: '2', logCode: 2 },
    { eventTheme: '3', logCode: 3 },
    { eventTheme: '4', logCode: 4 },
    { eventTheme: '5', logCode: 5 },
    { eventTheme: '6', logCode: 6 },
    { eventTheme: '7', logCode: 7 },
    { eventTheme: '8', logCode: 8 },
    { eventTheme: '9', logCode: 9 },
    { eventTheme: '10', logCode: 10 },
    { eventTheme: '11', logCode: 11 },
    { eventTheme: '12', logCode: 12 },
    { eventTheme: '13', logCode: 13 },
    { eventTheme: '14', logCode: 14 },
    { eventTheme: '15', logCode: 15 },
    { eventTheme: '16', logCode: 16 },
])
let allFilterEvents = reactive([
{ eventTheme: '1', logCode: 1 },
    { eventTheme: '2', logCode: 2 },
    { eventTheme: '3', logCode: 3 },
    { eventTheme: '4', logCode: 4 },
    { eventTheme: '5', logCode: 5 },
    { eventTheme: '6', logCode: 6 },
    { eventTheme: '7', logCode: 7 },
    { eventTheme: '8', logCode: 8 },
    { eventTheme: '9', logCode: 9 },
    { eventTheme: '10', logCode: 10 },
    { eventTheme: '11', logCode: 11 },
    { eventTheme: '12', logCode: 12 },
    { eventTheme: '13', logCode: 13 },
    { eventTheme: '14', logCode: 14 },
    { eventTheme: '15', logCode: 15 },
    { eventTheme: '16', logCode: 16 },
])
let pageNum = ref(1)
let pageSize = ref(10)

// 自定義v-el-select-loadmore指令
const vElSelectLoadmore = {
    beforeMount(el, binding) {
        /** 
         * vue2時(shí):
         * el.querySelector('.el-select-dropdown .el-select-dropdown__wrap');
         * vue3時(shí):
         * 在el-select給一個(gè)參數(shù)popper-class="event-select-poper"           
         * element-plus中el-select的選項(xiàng)是使用的popper.js生成的,無(wú)法直接獲取
        */
		const selectDom = document.querySelector('.event-select-poper .el-select-dropdown__wrap')
		let loadMores = function() {
            /**
            * scrollHeight 獲取元素內(nèi)容高度(只讀)
            * scrollTop 獲取或者設(shè)置元素的偏移值,常用于, 計(jì)算滾動(dòng)條的位置, 當(dāng)一個(gè)元素的容器沒(méi)有產(chǎn)生垂直方向的滾動(dòng)條, 那它的scrollTop的值默認(rèn)為0.
            * clientHeight 讀取元素的可見(jiàn)高度(只讀)
            * 如果元素滾動(dòng)到底, 下面等式返回true, 沒(méi)有則返回false:
            * ele.scrollHeight - ele.scrollTop === ele.clientHeight;
            */
            // 判斷是否到底
			const isBase = this.scrollHeight - this.scrollTop <= this.clientHeight + 20
			if (isBase) {
                // 增加防抖
				binding.value && binding.value()
			}
		}
        // 將獲取到的dom和函數(shù)掛載到el-select上,實(shí)例銷(xiāo)毀時(shí)好處理
		el.selectDomInfo = selectDom
		el.selectLoadMore = loadMores
        // 監(jiān)聽(tīng)滾動(dòng)事件
		selectDom?.addEventListener('scroll', loadMores.bind(selectDom))
	},
    // 實(shí)例銷(xiāo)毀
	beforeUnmount(el) {
		if (el.selectLoadMore) {
			el.selectDomInfo.removeEventListener('scroll', el.selectLoadMore)
			delete el.selectDomInfo
			delete el.selectLoadMore
		}
	}
}

watch(() => allFilterEvents, () => {
    let startIndex = pageNum.value * pageSize.value - pageSize.value
    let endIndex = pageNum.value * pageSize.value
    options = allFilterEvents.slice(startIndex, endIndex)
}, {
    immediate: true,
    deep: true
})

onBeforeMount(() => {
    loadEvents()
})

// 模擬懶加載
const loadmore = () => {
    // 數(shù)據(jù)加載完成之后,不需要再執(zhí)行懶加載
    if (allEvents.length <= options.length) { return }
    pageNum.value++
    nextTick(() => {
        loading.value = true
        let startIndex = pageNum.value * pageSize.value - pageSize.value
        let endIndex = pageNum.value * pageSize.value
        options = [
            ...options,
            ...allFilterEvents.slice(startIndex, endIndex)
        ]
        loading.value = false
    })
}

// 自定義過(guò)濾函數(shù)
const filterOptions = (query = '') => {
    pageNum.value = 1
    nextTick(() => {
        if(query === ''){
            // 搜索詞為空時(shí),顯示全部
            allFilterEvents = JSON.parse(JSON.stringify(allEvents))
        }else{
            // 搜索詞不為空時(shí),從所有關(guān)鍵字列表中篩選匹配項(xiàng)
            let arr = allEvents.filter((item) => {
                return item.includes(query)
            })
            $set(this, 'allFilterEvents', arr)
        }
    })
}

// 下拉框隱藏時(shí),重置分頁(yè)已經(jīng)過(guò)濾得到的列表
const handleVisibleChange = (visible) => {
    if(!visible){
        pageNum.value = 1
        nextTick(() => {
            allFilterEvents = JSON.parse(JSON.stringify(allEvents))
        })
    }
}

// 獲取事件列表
const loadEvents = () => {
    loading.value = true
    allFilterEvents = allEvents
    // 調(diào)用接口
    loading.value = false
}

const handleEventsChange = (val) => {
    emits('change', val)
}
</script>

el-select懶加載(自定義指令selectLazyload)實(shí)現(xiàn)大數(shù)據(jù)量展示和搜索

需求:在一個(gè)el-form里使用el-select提供選擇用戶(hù)的下拉框,但是每次打開(kāi)彈框的時(shí)候由于數(shù)據(jù)量過(guò)大都需要加載很久才能將數(shù)據(jù)渲染出來(lái),并且頁(yè)面異??D

封裝懶加載指令

在指令文件夾下新建文件 selectLazyload.js

export default {
    bind (el, binding) {
        // 獲取選擇器下的滾動(dòng)框DOM
        const SELECTWRAP_DOM = el.querySelector(
            `.el-select-dropdown__wrap`
        ); 
        // 如果找到了滾動(dòng)框DOM,則添加滾動(dòng)事件監(jiān)聽(tīng)器
        if (SELECTWRAP_DOM) {
            SELECTWRAP_DOM.addEventListener("scroll", function () {
                // 如果滾動(dòng)到底部,則調(diào)用傳入的回調(diào)函數(shù)
                const condition = SELECTWRAP_DOM.scrollHeight - SELECTWRAP_DOM.scrollTop <= SELECTWRAP_DOM.clientHeight;
                if (condition) {
                    binding.value();
                }
            });
        }
    },
};

在main.js或directive/index.js中注冊(cè)這個(gè)自定義指令

import selectLazyLoad from './module/selectLazyLoad'
Vue.directive('selectLazyLoad', selectLazyLoad)

html結(jié)構(gòu):在el-select上添加 

v-selectLazyLoad="loadMore":filter-method="userFilterMethod"

<el-select v-model="transferTesterNo" filterable placeholder="請(qǐng)選擇測(cè)試人" style="width:100%" v-selectLazyLoad="loadMore" :filter-method="userFilterMethod">
	<UOptins :isMobile="isMobile" v-for="{nickName, userName, organName, roleName} of options" :key="userName" :label="nickName" :organName="organName" :value="userName" :roleName="roleName" />
</el-select>

js結(jié)構(gòu)

// 加載更多
loadMore(){
	// 如果截取的長(zhǎng)度==獲取到的所有option長(zhǎng)度將不再截取
	if (this.options.length == this.userOptions?.length) return;
	this.userPageNum++;
	this.getScrollUser();
},
 
// 截取頁(yè)面顯示的實(shí)際option
getScrollUser(){
	// 過(guò)濾出前5條用戶(hù)信息  實(shí)際展示的數(shù)據(jù) options  全部數(shù)據(jù) userOptions
	this.options = this.userOptions.slice(0, this.userPageNum * 5);
},
// 搜索功能
userFilterMethod(value){
	// 手動(dòng)觸發(fā)下拉框回滾至頂部,避免觸發(fā)v-selectLazyLoad指令
	document.querySelector(`.el-select-dropdown__wrap`).scrollTop = 0;
	if (!value?.length) return this.getScrollUser();
	this.options = this.userOptions.filter((item) => item.nickName?.includes(value)) || [];
},

首次加載需要在 獲取數(shù)據(jù)的接口內(nèi)寫(xiě)上

this.userOptions = rows
this.getScrollUser()

// 在data 中定義變量 
userOptions: [],
options: [],
userPageNum: 1,

這樣即可實(shí)現(xiàn) 在滾動(dòng)到底部時(shí)動(dòng)態(tài)加載后面的數(shù)據(jù),且可以搜索

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue實(shí)現(xiàn)滾動(dòng)加載的表格

    vue實(shí)現(xiàn)滾動(dòng)加載的表格

    在系統(tǒng)開(kāi)發(fā)中遇到了這么一個(gè)問(wèn)題:后端一次性返回上百條的數(shù)據(jù),我需要把返回的數(shù)據(jù)全部顯示在表格里,而且甲方爸爸明確指定了表格是不允許使用分頁(yè)的??墒钱?dāng)使用a-table裝載上百條數(shù)據(jù)時(shí),頁(yè)面出現(xiàn)了明顯的卡頓現(xiàn)象。只能使用滾動(dòng)加載的方案來(lái)代替了。
    2021-06-06
  • vue中為什么在組件內(nèi)部data是一個(gè)函數(shù)而不是一個(gè)對(duì)象

    vue中為什么在組件內(nèi)部data是一個(gè)函數(shù)而不是一個(gè)對(duì)象

    這篇文章主要介紹了vue中為什么在組件內(nèi)部data是一個(gè)函數(shù)而不是一個(gè)對(duì)象,本文通過(guò)示例代碼給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • vue2.0基于vue-cli+element-ui制作樹(shù)形treeTable

    vue2.0基于vue-cli+element-ui制作樹(shù)形treeTable

    這篇文章主要介紹了vue2.0基于vue-cli+element-ui制作樹(shù)形treeTable,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • vue阻止事件冒泡和捕獲方式

    vue阻止事件冒泡和捕獲方式

    這篇文章主要介紹了vue阻止事件冒泡和捕獲方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-06-06
  • 詳解vue中使用express+fetch獲取本地json文件

    詳解vue中使用express+fetch獲取本地json文件

    本篇文章主要介紹了詳解vue中使用express+fetch獲取本地json文件,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-10-10
  • Vue3封裝全局自定義指令實(shí)現(xiàn)按鈕權(quán)限控制功能實(shí)例

    Vue3封裝全局自定義指令實(shí)現(xiàn)按鈕權(quán)限控制功能實(shí)例

    在Vue應(yīng)用中自定義指令是一種強(qiáng)大的功能,可以用于封裝DOM操作邏輯,這篇文章主要介紹了Vue3封裝全局自定義指令實(shí)現(xiàn)按鈕權(quán)限控制功能的相關(guān)資料,需要的朋友可以參考下
    2025-07-07
  • vue彈窗消息組件的使用方法

    vue彈窗消息組件的使用方法

    這篇文章主要為大家詳細(xì)介紹了vue彈窗消息組件的使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • Vue使用正則校驗(yàn)文本框?yàn)檎麛?shù)

    Vue使用正則校驗(yàn)文本框?yàn)檎麛?shù)

    這篇文章主要介紹了Vue使用正則校驗(yàn)文本框?yàn)檎麛?shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • vue進(jìn)入頁(yè)面時(shí)滾動(dòng)條始終在底部代碼實(shí)例

    vue進(jìn)入頁(yè)面時(shí)滾動(dòng)條始終在底部代碼實(shí)例

    這篇文章主要介紹了vue進(jìn)入頁(yè)面時(shí)滾動(dòng)條始終在底部,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 前端VUE3項(xiàng)目部署到linux服務(wù)器(CentOS?7)完整步驟

    前端VUE3項(xiàng)目部署到linux服務(wù)器(CentOS?7)完整步驟

    這篇文章主要介紹了前端VUE3項(xiàng)目部署到linux服務(wù)器(CentOS?7)的相關(guān)資料,包括項(xiàng)目打包、連接服務(wù)器、安裝和配置Nginx、上傳文件以及配置Nginx,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2026-01-01

最新評(píng)論

慈利县| 天峨县| 同仁县| 明水县| 淮南市| 平邑县| 高密市| 比如县| 左权县| 建瓯市| 德昌县| 天祝| 青河县| 福贡县| 蒙自县| 玛纳斯县| 马尔康县| 德钦县| 类乌齐县| 微博| 连南| 高密市| 秦皇岛市| 巴青县| 雷山县| 尉氏县| 丹巴县| 乾安县| 凌云县| 潜山县| 庆阳市| 乌鲁木齐市| 莎车县| 嘉鱼县| 嘉荫县| 扶余县| 阿合奇县| 厦门市| 绵竹市| 怀安县| 达州市|