一、基礎內核-自定義指令
1.背景
2.定義
3.使用
4.注意
當編輯時需要回顯,此時由于分頁導致可能匹配不到對應label文本顯示,此時可以這樣解決
二、升級使用-二次封裝組件
三、核心代碼
1.自定義指令
定義
----------------selectLoadMoreDirective.ts--------------------import { Directive, DirectiveBinding, nextTick } from "vue";
import { debounce } from "../utils/index";const loadMore: Directive = {beforeMount(el: any, binding: DirectiveBinding) {// 查詢下拉框的滾動容器const popperClassName = el.getAttribute("popper-class-name");let selectDom = document.querySelector(`.${popperClassName} .el-select-dropdown__wrap`);function loadMores(this: any) {// 判斷是否滾動到底部const isBase =this.scrollHeight - this.scrollTop - 1 <= this.clientHeight;if (isBase) {binding.value && binding.value(); // 觸發綁定的回調函數}}// 使用防抖處理滾動事件const debouncedLoadMore = debounce(loadMores, 300); // 設置防抖時間為300msel.selectDomInfo = selectDom;el.userLoadMore = debouncedLoadMore; // 將防抖后的函數賦值給 el.userLoadMorenextTick(() => {selectDom?.addEventListener("scroll", debouncedLoadMore);});},beforeUnmount(el: any) {if (el.userLoadMore) {el.selectDomInfo?.removeEventListener("scroll", el.userLoadMore);delete el.selectDomInfo;delete el.userLoadMore;}},
};export default loadMore;
全局注冊?
------------------main.ts-----------------
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import router from './router'
import loadMore from '@/directive/selectLoadMoreDirective'const app = createApp(App)app.use(ElementPlus)
app.use(router)
app.directive('loadMore', loadMore)
app.mount('#app')
2.二次封裝組件代碼
定義
-------------------------CustomSelect.vue---------------------------<template><el-selectv-model="selectedValue"v-loadMore="loadMore":popper-class="popperClassName":popper-class-name="popperClassName":remote-method="remoteMethod":loading="loading":placeholder="placeholder":style="style"filterableremote><el-optionv-for="item in options":key="item.value":label="item.label":value="item"/></el-select>
</template><script setup lang="ts">
import { ref, watch } from "vue";// 定義 props
const props = defineProps({// 雙向綁定值modelValue: {type: [Object, String, Number],default: null,required: true},placeholder: {type: String,default: "請選擇",},popperClassName: {type: String,default: "",required: true},remoteMethod: {type: Function,required: true},loading: {type: Boolean,default: false,},style: {type: Object,default: () => ({}),},loadMore: {type: Function,required: true,},options: {type: Array<{ value: number; label: string }>,default: () => [],required: true},
});// 加載狀態
const loading = ref(false);// 定義 emits
const emit = defineEmits(["update:modelValue"]);// 雙向綁定值
const selectedValue = ref(props.modelValue);// 監聽 modelValue 的變化
watch(() => props.modelValue,(newVal) => {selectedValue.value = newVal;}
);// 監聽 selectedValue 的變化并觸發更新
watch(selectedValue, (newVal) => {emit("update:modelValue", newVal);
});
</script><style scoped>
/* 自定義樣式 */
</style>
使用
----------------------xxx.vue------------------------------<template><CustomSelectv-model="selectedGrade"placeholder="選擇年級"popper-class-name="grade_select2":remote-method="searchGrades":style="{ width: '100px', marginRight: '10px' }":load-more="() => loadMore('grade')":options="grades"/>
</template>