vue实现时间滑块
Vue 实现时间滑块
使用原生 HTML5 input range
通过 HTML5 的 input[type="range"] 结合 Vue 的数据绑定实现基础时间滑块:
<template>
<div>
<input
type="range"
min="0"
max="1440"
step="15"
v-model="minutes"
@input="updateTime"
>
<p>当前时间: {{ formattedTime }}</p>
</div>
</template>
<script>
export default {
data() {
return {
minutes: 0
}
},
computed: {
formattedTime() {
const hours = Math.floor(this.minutes / 60)
const mins = this.minutes % 60
return `${hours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}`
}
},
methods: {
updateTime() {
console.log('Selected time:', this.formattedTime)
}
}
}
</script>
使用第三方组件库
Element UI 的滑块组件提供更丰富的功能:
<template>
<el-slider
v-model="minutes"
:min="0"
:max="1440"
:step="15"
:format-tooltip="formatTooltip"
@change="handleChange"
/>
</template>
<script>
export default {
data() {
return {
minutes: 0
}
},
methods: {
formatTooltip(val) {
const hours = Math.floor(val / 60)
const mins = val % 60
return `${hours}:${mins < 10 ? '0' + mins : mins}`
},
handleChange(val) {
console.log('时间变更:', this.formatTooltip(val))
}
}
}
</script>
自定义滑块组件
创建带有时间刻度的自定义滑块:
<template>
<div class="time-slider">
<div class="slider-track" ref="track" @click="handleTrackClick">
<div
class="slider-thumb"
:style="{ left: thumbPosition + 'px' }"
@mousedown="startDrag"
></div>
</div>
<div class="time-marks">
<span v-for="hour in 24" :key="hour">{{ hour - 1 }}:00</span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
currentTime: 0,
isDragging: false
}
},
computed: {
thumbPosition() {
return (this.currentTime / 1440) * this.$refs.track?.offsetWidth || 0
}
},
methods: {
startDrag(e) {
this.isDragging = true
document.addEventListener('mousemove', this.handleDrag)
document.addEventListener('mouseup', this.stopDrag)
},
handleDrag(e) {
if (!this.isDragging) return
this.updateTimeFromPosition(e.clientX)
},
stopDrag() {
this.isDragging = false
document.removeEventListener('mousemove', this.handleDrag)
document.removeEventListener('mouseup', this.stopDrag)
},
handleTrackClick(e) {
this.updateTimeFromPosition(e.clientX)
},
updateTimeFromPosition(clientX) {
const rect = this.$refs.track.getBoundingClientRect()
const position = Math.min(Math.max(0, clientX - rect.left), rect.width)
this.currentTime = Math.round((position / rect.width) * 1440)
this.$emit('time-change', this.currentTime)
}
}
}
</script>
<style>
.time-slider {
width: 100%;
position: relative;
}
.slider-track {
height: 4px;
background: #ddd;
position: relative;
cursor: pointer;
}
.slider-thumb {
width: 16px;
height: 16px;
background: #409eff;
border-radius: 50%;
position: absolute;
top: -6px;
transform: translateX(-50%);
cursor: grab;
}
.time-marks {
display: flex;
justify-content: space-between;
margin-top: 10px;
}
</style>
双向绑定时间范围
实现时间范围选择滑块:
<template>
<div>
<el-slider
v-model="timeRange"
range
:min="0"
:max="1440"
:step="15"
:format-tooltip="formatTooltip"
@change="handleRangeChange"
/>
<p>选择的时间范围: {{ formatTooltip(timeRange[0]) }} - {{ formatTooltip(timeRange[1]) }}</p>
</div>
</template>
<script>
export default {
data() {
return {
timeRange: [480, 1020] // 默认8:00-17:00
}
},
methods: {
formatTooltip(val) {
const hours = Math.floor(val / 60)
const mins = val % 60
return `${hours}:${mins < 10 ? '0' + mins : mins}`
},
handleRangeChange(val) {
console.log('时间范围变更:', val.map(this.formatTooltip))
}
}
}
</script>
注意事项
- 时间值通常以分钟数存储(0-1440对应00:00-24:00)
- 移动端需要添加触摸事件支持
- 复杂场景可考虑使用专门的日期时间选择器库
- 性能优化:频繁更新时考虑使用防抖处理







