element ui中日期和时间选择器(DateTimePicker)是一个常见且重要的组件。它允许用户轻松地选择日期和时间,极大地提升了用户体验。然而,在某些场景下,用户可能需要更细粒度的控制,例如单独清除已选择的时间而保留日期。效果如下图,本文将带领你一步步封装一个DateTimePicker组件,实现时间的独立清除功能。
实现步骤
1、在components中新建组件dataTimePicker
<template>
<el-date-picker
:popper-class="uniqueId"
style="margin-left: 5px"
type="datetime"
v-model="dataTimeValue"
:placeholder="placeholder"
@change="changeDateTime"
@focus="onFocus"
>
</el-date-picker>
</template>
1、1给每个组件自定义一个唯一的下拉框class名
data() {
return {
dataTimeValue: "", // 初始化值
uniqueId: `date-picker-${Math.random().toString(36).substring(2, 15)}`, // 生成一个唯一的ID
isAddCloseIcon: false,
};
},
1.2 该组件接收两个props
props: {
timeValue: {
type: Date, // 初始展示时间
required: false,
},
placeholder: {
type: String,
require: false,
default: "起始时间",
},
},
1.3 在 onFocus事件中,添加清除图标,因为只有当onFocus触发时,下拉框才显示,才能获取到下拉框dom
onFocus() {
if (this.isAddCloseIcon) return; // 避免重复添加
this.$nextTick(() => {
this.timeDiv = document.querySelectorAll(
`.${this.uniqueId} .el-date-picker__editor-wrap .el-input`,
this.$el
)[1];
this.span = document.createElement("span");
this.span.innerHTML = `<i class="el-icon-circle-close"></i>`;
this.span.style.position = "absolute";
this.span.style.right = "10px";
this.span.style.cursor = "pointer";
this.span.style.display = "none"; // 初始时隐藏span
this.timeDiv.appendChild(this.span);
// 鼠标移入事件
this.timeDiv.addEventListener("mouseenter",this.handleMouseenter);
// 鼠标移出事件
this.timeDiv.addEventListener("mouseleave", this.handleMouseLeave);
// 点击事件,清除时间置为00:00:00
this.span.addEventListener("click", this.clearDateTimeValue);
this.isAddCloseIcon = true;
});
},
1.4 清除时间事件以及鼠标移入显示图标移除隐藏图标:
clearDateTimeValue() {
this.dataTimeValue = this.$moment(this.dataTimeValue)
.startOf("day")
.toISOString();
},
handleMouseLeave() {
this.span.style.display = "none";
},
handleMouseenter() {
this.span.style.display = "inline";
}
1.5 时间变化时通知父组件:
changeDateTime(value) {
this.dataTimeValue = value;
this.$emit("change", value);
},
1.6 组件销毁时,移除监听事件:
beforeDestroy() {
// 组件销毁前清理事件监听器
this.span.removeEventListener('click',this.clearDateTimeValue)
this.timeDiv.removeEventListener('mouseenter',this.handleMouseenter)
this.timeDiv.removeEventListener('mouseleave',this.handleMouseLeave)
this.span = null
this.timeDiv = null
},
完整代码:
dataTimePicker.vue:
<template>
<el-date-picker
:popper-class="uniqueId"
style="margin-left: 5px"
type="datetime"
v-model="dataTimeValue"
:placeholder="placeholder"
@change="changeDateTime"
@focus="onFocus"
>
</el-date-picker>
</template>
<script>
export default {
props: {
timeValue: {
type: Date,
required: false,
},
placeholder: {
type: String,
require: false,
default: "起始时间",
},
},
data() {
return {
dataTimeValue: "", // 初始化值
uniqueId: `date-picker-${Math.random().toString(36).substring(2, 15)}`, // 生成一个唯一的ID
isAddCloseIcon: false,
};
},
mounted() {
this.dataTimeValue = this.timeValue;
},
methods: {
changeDateTime(value) {
this.dataTimeValue = value;
this.$emit("change", value);
},
onFocus() {
if (this.isAddCloseIcon) return; // 避免重复添加
this.$nextTick(() => {
this.timeDiv = document.querySelectorAll(
`.${this.uniqueId} .el-date-picker__editor-wrap .el-input`,
this.$el
)[1];
this.span = document.createElement("span");
this.span.innerHTML = `<i class="el-icon-circle-close"></i>`;
this.span.style.position = "absolute";
this.span.style.right = "10px";
this.span.style.cursor = "pointer";
this.span.style.display = "none"; // 初始时隐藏span
this.timeDiv.appendChild(this.span);
// 鼠标移入事件
this.timeDiv.addEventListener("mouseenter",this.handleMouseenter);
// 鼠标移出事件
this.timeDiv.addEventListener("mouseleave", this.handleMouseLeave);
this.span.addEventListener("click", this.clearDateTimeValue);
this.isAddCloseIcon = true;
});
},
clearDateTimeValue() {
this.dataTimeValue = this.$moment(this.dataTimeValue)
.startOf("day")
.toISOString();
},
handleMouseLeave() {
this.span.style.display = "none";
},
handleMouseenter() {
this.span.style.display = "inline";
}
},
beforeDestroy() {
// 组件销毁前清理事件监听器
this.span.removeEventListener('click',this.clearDateTimeValue)
this.timeDiv.removeEventListener('mouseenter',this.handleMouseenter)
this.timeDiv.removeEventListener('mouseleave',this.handleMouseLeave)
this.span = null
this.timeDiv = null
},
};
</script>
2、在父组件引入:
<template>
<dateTimePicker :timeValue="startTime" @change="changeDateTime"></dateTimePicker>
</template>
<script type="text/ecmascript-6">
import dateTimePicker from '@/components/dataTimePicker.vue'
export default {
...,
methods: {
changeDateTime(value) {
console.log('变化',value)
}
}
</script>
3、总结
通过以上方法,我们可以实现在不改变日期的情况下单独清除时间功能,实际上就是在element ui原本的el-date-picker组件上进行改装,增加一个清除按钮并绑定清除事件来实现。实际应用中,你可以根据具体需求进一步扩展和定制这个组件,以满足不同场景下的使用。希望这篇文章能对你有所帮助!