一、基础内核-自定义指令
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>