摘要:
今天遇到一个vue3使用elementPlus的select选择商品数据的时候需要分页加载商品,但是找了一圈elementPlus没有分页的事件,只能自己写,自定义形式和嵌套一层option选项中滚动触发上拉加载数据!
自定义指令(推荐)
<template>
<el-select v-model="_modelValue" remote reserve-keyword @visible-change="handleVisibleChange" @change="handelChange" :remote-method="remoteMethod" filterable :loading="loading" clearable v-loadMore="loadMore" :multiple="multiple" :disabled="disabled" :placeholder="placeholder" :teleported="false">
<el-option v-for="item in optionsList" :key="item[optionName.value]" :label="item[optionName.label]" :value="item[optionName.value]" />
</el-select>
</template>
<script lang="ts" setup>
const { proxy } = getCurrentInstance();
const { selectLoadMoreDefault } = proxy.constants;
const props = defineProps({
options: {
type: Array
},
modelValue: {
type: [String, Number]
},
optionsName: {
type: Object,
default: () => ({})
},
total: {
type: Number,
default: 0
},
pageSize: {
type: Number,
default: 0
},
pageNum: {
type: Number,
default: 0
},
getList: {
type: Function
},
placeholder: {
type: String,
default: '请输入/选择'
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: false
},
clearable: {
type: Boolean,
default: true
},
// 除分页参数的其他参数
otherParams: {
type: Object,
default: () => ({})
}
});
const emits = defineEmits(['changeData', 'update:modelValue']);
const pageSize = computed(
() => props.pageSize || selectLoadMoreDefault.pageSize
);
const pageNum = computed(() => props.pageNum || selectLoadMoreDefault.pageNum);
const queryParams = ref({
pageSize: pageSize.value,
pageNum: pageNum.value,
name: ''
});
const visible = ref(false);
const _modelValue = ref(props.modelValue);
watch(
() => [props.modelValue, props.total],
(val) => {
_modelValue.value = val[0];
emits('update:modelValue', val[0]);
if (!val[1]) {
queryParams.value.pageNum = 1;
}
}
);
const loading = ref(false);
const isMounted = ref(false);
const optionsList = computed(() => props.options);
onMounted(() => {
isMounted.value = true;
});
onUnmounted(() => {
isMounted.value = false;
});
// 下拉选属性配置
const optionName = computed(() => {
return {
label: props.optionsName?.label ?? 'label',
value: props.optionsName?.value ?? 'value'
};
});
const handelChange = (val) => {
emits('changeData', val);
emits('update:modelValue', val);
};
const loadMore = () => {
let sum = queryParams.value.pageNum * queryParams.value.pageSize;
if (sum >= props.total) return;
visible.value && remoteMethod(queryParams.value.name, false);
};
const remoteMethod = (query, isEmpty = true) => {
if (visible.value) {
queryParams.value.name = query;
queryParams.value.pageNum = isEmpty ? 1 : queryParams.value.pageNum + 1;
setTimeout(() => {
props.getList({ ...queryParams.value, ...props.otherParams }, isEmpty);
}, 200);
}
};
// 控制下拉框的显示隐藏
const handleVisibleChange = (isVisible) => {
visible.value = isVisible;
};
</script>
Infinite Scroll的无限滚动 =》v-infinite-scroll
<template>
<el-select style="width: 100%" v-if="isMounted" v-model="_modelValue" remote reserve-keyword @visible-change="handleVisibleChange" @change="handelChange" :remote-method="remoteMethod" filterable :loading="loading" clearable :multiple="multiple" :disabled="disabled" :placeholder="placeholder">
<div v-infinite-scroll="loadMore" :infinite-scroll-delay="500" style="overflow-y: hidden">
<el-option v-for="item in optionsList" :key="item[optionName.value]" :label="item[optionName.label]" :value="item[optionName.value]" />
</div>
</el-select>
</template>
<script lang="ts" setup>
const { proxy } = getCurrentInstance();
const { selectLoadMoreDefault } = proxy.constants;
const props = defineProps({
options: {
type: Array
},
modelValue: {
type: [String, Number]
},
optionsName: {
type: Object,
default: () => ({})
},
total: {
type: Number,
default: 0
},
pageSize: {
type: Number,
default: 0
},
pageNum: {
type: Number,
default: 0
},
getList: {
type: Function
},
placeholder: {
type: String,
default: '请输入/选择'
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: false
},
clearable: {
type: Boolean,
default: true
},
// 除分页参数的其他参数
otherParams: {
type: Object,
default: () => ({})
}
});
const emits = defineEmits(['changeData', 'update:modelValue']);
const pageSize = computed(
() => props.pageSize || selectLoadMoreDefault.pageSize
);
const pageNum = computed(() => props.pageNum || selectLoadMoreDefault.pageNum);
const queryParams = ref({
pageSize: pageSize.value,
pageNum: pageNum.value,
name: ''
});
const visible = ref(false);
const _modelValue = ref(props.modelValue);
watch(
() => [props.modelValue, props.total],
(val) => {
_modelValue.value = val[0];
emits('update:modelValue', val[0]);
if (!val[1]) {
queryParams.value.pageNum = 1;
}
}
);
const loading = ref(false);
const isMounted = ref(false);
const optionsList = computed(() => props.options);
onMounted(() => {
isMounted.value = true;
});
// 下拉选属性配置
const optionName = computed(() => {
return {
label: props.optionsName?.label ?? 'label',
value: props.optionsName?.value ?? 'value'
};
});
const handelChange = (val) => {
emits('changeData', val);
emits('update:modelValue', val);
};
const loadMore = () => {
let sum = queryParams.value.pageNum * queryParams.value.pageSize;
if (sum >= props.total) return;
visible.value && remoteMethod(queryParams.value.name, false);
};
const remoteMethod = (query, isEmpty = true) => {
if (visible.value) {
queryParams.value.name = query;
queryParams.value.pageNum = isEmpty ? 1 : queryParams.value.pageNum + 1;
setTimeout(() => {
props.getList({ ...queryParams.value, ...props.otherParams }, isEmpty);
}, 200);
}
};
// 控制下拉框的显示隐藏
const handleVisibleChange = (isVisible) => {
visible.value = isVisible;
};
</script>