问题描述
el-date-picker 组件在 Element Plus 库中用于日期选择(daterange、datetimerange、monthrange、yearrange),并且在选择日期范围时确实会触发两次 change 事件。这是因为,当用户选择了范围的开始时,会立即触发一次 change 事件。而当用户选择了范围的结束时,又会触发一次 change 事件。
解决方案
为了解决这个问题,可以采取以下几种策略:
延迟更新
html
<script setup lang="ts">
import { ElementPlus } from '@element-plus/icons-vue';
import { version as epVersion } from 'element-plus';
import { ref, version as vueVersion } from 'vue';
const value2 = ref("");
let debounceTimer = null;
const handleChangeDebounced = (val:any) => {
handleChange(val);
}
const handleChange = (val:any) => {
// 清除已经设置的定时器,以防止多个事件被延迟执行
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
console.log('Date changed:', val);
}, 300); // 延迟300毫秒执行
};
</script>
<template>
<p>
<el-icon color="var(--el-color-primary)"><ElementPlus /></el-icon>
Element Plus {{ epVersion }} + Vue {{ vueVersion }}
</p>
<el-divider/>
<el-date-picker
v-model.lazy="value2"
type="datetimerange"
range-separator="To"
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="handleChangeDebounced"
/>
</template>
【注意】这种方案适合所有时间范围选择(daterange、datetimerange、monthrange、yearrange),但考虑到 JavaScript 是单线程的,如果在指定的时间点上有大量代码正在执行,setTimeout 里的函数可能会被延迟执行。每一个 setTimeou t都是在增加一个新的JavaScript任务,绝对的会影响浏览器主线程的,会造成一定程度达到卡机。
change、clear事件结合
html
<script setup lang="ts">
import { ElementPlus } from '@element-plus/icons-vue'
import { version as epVersion } from 'element-plus'
import { ref, version as vueVersion } from 'vue'
const value1 = ref("");
const handlerDateChange = (val:any) => {
if(val){
console.log(8)
}
}
const handlerDateClear = () => {
console.log(12)
}
</script>
<template>
<p>
<el-icon color="var(--el-color-primary)"><ElementPlus /></el-icon>
Element Plus {{ epVersion }} + Vue {{ vueVersion }}
</p>
<el-date-picker
v-model="value1"
type="monthrange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="handlerDateChange"
@clear="handlerDateClear"
/>
</template>
【注意】这种方案适合daterange、monthrange、yearrange等三种时间范围选择。