人生就像一场迷雾中的漫步,常常是后知后觉。
最近遇到一个页面要求维护,我打开代码一看我滴个天呀,全是代码所有逻辑都放在这个页面了。受不了了但是又能怎么办之前也是我写的,时间紧任务重我就不管三七二十一直接搞了。现在头疼的又是我自己哈哈哈哈,自作自受吧!
这个页面我想了想要优化我能想到的就是封装组件,我先封装了日期选择的组件,我自己写了一个基本的有功能的然后就把代码丢给了AI让他帮我分析了一下。
优化点
- 使用
v-model替代value+input(符合 Vue 2.2+ 或 Vue 3 的最佳实践) - 避免直接修改
props(你的代码中没有直接修改props,但可以进一步优化数据流) - 优化
defaultDate逻辑(避免在created和openCalendar中重复计算) - 使用
computed替代watch(减少不必要的响应式开销) - 增加
formatter函数支持(让父组件自定义日期格式化逻辑) - 优化
disabled状态的 UI 反馈(如禁用点击效果) - 增加
minDate和maxDate的可配置性(目前是硬编码的) - 优化日期格式化逻辑(避免重复创建
Date对象)
优化后的代码
1. 模板部分 (<template>)
vue
<template>
<div>
<van-cell
:title="title"
:value="displayDate || placeholder"
:is-link="!disabled"
:class="{ 'disabled-cell': disabled }"
@click="openCalendar"
/>
<van-calendar
v-model="showCalendar"
color="#1989fa"
type="range"
:default-date="defaultDate"
:min-date="minDate"
:max-date="maxDate"
@confirm="onConfirm"
/>
</div>
</template>
2. 脚本部分 (<script>)
vue
<script>
export default {
name: "RangeDatePicker",
props: {
title: {
type: String,
required: true,
},
placeholder: {
type: String,
default: "请选择",
},
value: {
type: Array, // [startDate, endDate]
default: () => [],
},
format: {
type: String,
default: "YYYY-MM-DD",
},
disabled: {
type: Boolean,
default: false,
},
minDate: {
type: Date,
default: () => new Date(2020, 0, 31),
},
maxDate: {
type: Date,
default: () => new Date(2040, 0, 31),
},
formatter: {
type: Function, // 自定义日期格式化函数
default: null,
},
},
data() {
return {
showCalendar: false,
defaultDate: [], // 用于初始化日历选中状态
};
},
computed: {
// 显示的日期字符串(如 "2023-01-01 ~ 2023-01-05")
displayDate() {
if (!this.value || this.value.length < 2) return "";
const [start, end] = this.value;
return `${this.formatDate(start)} ~ ${this.formatDate(end)}`;
},
},
watch: {
// 监听 value 变化,更新 defaultDate(用于日历初始化)
value: {
immediate: true,
handler(newVal) {
if (newVal && newVal.length === 2) {
this.defaultDate = newVal.map((date) => new Date(date));
}
},
},
},
methods: {
// 打开日历
openCalendar() {
if (this.disabled) return;
this.showCalendar = true;
},
// 确认选择
onConfirm(dates) {
const formattedDates = dates.map((date) => this.formatDate(date));
this.$emit("input", formattedDates); // 用于 v-model
this.$emit("change", formattedDates); // 额外事件
this.showCalendar = false;
},
// 格式化日期(优先使用 formatter,否则用 format)
formatDate(date) {
if (this.formatter) {
return this.formatter(date);
}
const d = new Date(date);
const year = d.getFullYear();
const month = String(d.getMonth() + 1).padStart(2, "0");
const day = String(d.getDate()).padStart(2, "0");
return this.format
.replace("YYYY", year)
.replace("MM", month)
.replace("DD", day);
},
},
};
</script>
3. 样式部分 (<style>)
vue
<style scoped>
.disabled-cell {
opacity: 0.6;
pointer-events: none;
}
</style>
ok就这样 🚀