SelectTime 组件设计文档
概述
SelectTime 组件是本组件库中用于时间选择的交互组件。它延续了我们组件库一贯的设计理念,采用"关注点分离"和"逻辑抽象"的原则,通过 useSelectTimeComputed 等核心逻辑实现了一套完整且易用的时间选择解决方案。
SelectTime 组件专注于处理用户的时间选择操作,为用户提供了一套直观、美观的时间选择功能,支持单时间选择和时间范围选择两种模式,并具有良好的可定制性。
设计理念
分层架构
SelectTime 组件严格按照三层架构设计:
- 结构层 selectTime.vue - 负责组件的 DOM 结构和基本布局
- 逻辑层 selectTimeComputed.ts - 处理复杂的响应式计算和交互逻辑
- 表现层 selectTime.scss - 定义组件的视觉呈现和样式规则
逻辑抽象
SelectTime 组件将复杂的逻辑抽象为核心函数:
- useSelectTimeComputed - 处理时间选择器的核心逻辑
这种设计使得组件本身只需要声明所需逻辑,而具体的计算由逻辑函数完成。
核心功能设计
Props 结构化设计
SelectTime 组件的 props 设计简洁明了:
typescript
export const selectTimeProps = {
modelValue: {
type: [String, Array] as PropType<string | string[]>,
default: ''
},
range: { type: Boolean, default: false },
hourOptions: {
type: Array as PropType<number[]>,
default: () => Array.from({ length: 24 }, (_, i) => i),
},
minuteOptions: {
type: Array as PropType<number[]>,
default: () => Array.from({ length: 60 }, (_, i) => i),
},
};这种设计提供了足够的灵活性,支持多种使用场景。
模式系统
SelectTime 组件支持两种模式:
- 单时间模式 - 选择单一时间点(默认模式)
- 时间范围模式 - 选择时间范围(通过 range 属性启用)
样式系统设计
CSS 样式控制
SelectTime 组件通过 SCSS 实现样式控制:
- 深色主题 - 默认采用深色背景和浅色文本
- 悬停效果 - 鼠标悬停时的背景色变化
- 聚焦效果 - 获得焦点时的边框高亮
- 自定义滚动条 - 下拉列表的滚动条样式定制
尺寸系统
SelectTime 组件具有固定的尺寸设计:
- 高度 - 30px 的标准高度
- 宽度 - 自适应内容宽度
- 内边距 - 8px 上下,12px 左右的内边距
状态样式
SelectTime 组件根据不同状态提供相应的样式:
- 默认状态 - 标准下拉框样式
- 悬停状态 - 鼠标悬停时的背景色变化
- 聚焦状态 - 获得焦点时的蓝色边框高亮
- 禁用状态 - 选项禁用时的视觉效果
组件结构设计
整体结构
SelectTime 组件的整体结构如下:
html
<div class="time-picker">
<div v-if="range" class="time-range-picker">
<!-- 起始时间选择 -->
<div class="time-input-group">
<div class="custom-time-picker">
<select v-model="selectedHourStart" class="time-select">...</select>
<span class="time-separator">:</span>
<select v-model="selectedMinuteStart" class="time-select">...</select>
</div>
</div>
<span class="time-range-separator">至</span>
<!-- 结束时间选择 -->
<div class="time-input-group">
<div class="custom-time-picker">
<select v-model="selectedHourEnd" class="time-select">...</select>
<span class="time-separator">:</span>
<select v-model="selectedMinuteEnd" class="time-select">...</select>
</div>
</div>
</div>
<div v-else class="time-input-group single">
<!-- 单时间选择 -->
<div class="custom-time-picker single-picker">
<select v-model="selectedHour" class="time-select">...</select>
<span class="time-separator">:</span>
<select v-model="selectedMinute" class="time-select">...</select>
</div>
</div>
</div>下拉选择结构
时间选择下拉框结构如下:
html
<select v-model="selectedHour" class="time-select">
<option value="" disabled hidden>时</option>
<option v-for="h in hourOptions" :key="`hour-${h}`" :value="h">
{{ String(h).padStart(2, '0') }}
</option>
</select>交互设计
时间选择
SelectTime 组件支持时间选择:
typescript
// 单时间模式
const t = formatTime(selectedHour.value, selectedMinute.value);
if (t) emit('update:modelValue', t);
// 时间范围模式
const t1 = formatTime(selectedHourStart.value, selectedMinuteStart.value);
const t2 = formatTime(selectedHourEnd.value, selectedMinuteEnd.value);
if (t1 && t2) emit('update:modelValue', [t1, t2]);时间格式化
SelectTime 组件支持时间格式化:
typescript
function formatTime(h: string | number, m: string | number): string {
if (h === '' || m === '') return '';
const hh = typeof h === 'string' ? parseInt(h) : h;
const mm = typeof m === 'string' ? parseInt(m) : m;
return `${String(hh).padStart(2, '0')}:${String(mm).padStart(2, '0')}`;
}模式切换
SelectTime 组件支持模式切换时的状态重置:
typescript
watch(
() => props.range,
(newRange) => {
emit('update:modelValue', newRange ? ['', ''] : '');
}
);扩展性设计
SelectTime 组件具备良好的扩展性:
- 自定义时间选项:通过 hourOptions 和 minuteOptions 属性自定义可选时间
- 双模式支持:支持单时间选择和时间范围选择
- 双向绑定:支持 v-model 双向数据绑定
- 样式定制:通过 CSS 变量支持样式定制
- 主题适配:默认采用深色主题,易于适配其他主题
样式细节
SelectTime 组件在样式处理上有以下特点:
- 下拉箭头:使用 SVG 图标实现自定义下拉箭头
- 滚动条样式:自定义滚动条样式以匹配整体设计风格
- 响应式设计:组件尺寸适合各种布局环境
- 无障碍设计:支持键盘导航和屏幕阅读器
- 一致性:与组件库其他表单组件保持样式一致性
性能优化
通过以下方式优化性能:
- 使用 computed 属性缓存计算结果
- 将复杂逻辑移至独立的函数中
- 避免不必要的重新渲染
- 使用 Vue 3 Composition API 提高运行效率
- 合理使用 watch 和 watchEffect 进行状态监听
设计价值
SelectTime 组件延续了我们组件库的设计哲学:
- 关注点分离:结构、样式、逻辑完全解耦
- 高度复用:通过函数抽象通用逻辑
- 易于维护:清晰的代码结构和命名规范
- 可扩展性强:支持丰富的定制选项
- 一致性:与 SelectDate、Select、PickColor、Rate、Switch、Checkbox、Radio 等其他组件保持一致的设计语言