vue实现滑块区间
Vue 实现滑块区间组件
使用原生 input range 实现
通过两个 input[type="range"] 元素实现基础的双滑块功能。这种方法简单直接,适合基础需求。
<template>
<div class="range-slider">
<input
type="range"
v-model="minValue"
:min="min"
:max="max"
@input="updateMin"
>
<input
type="range"
v-model="maxValue"
:min="min"
:max="max"
@input="updateMax"
>
<div>当前范围: {{ minValue }} - {{ maxValue }}</div>
</div>
</template>
<script>
export default {
data() {
return {
min: 0,
max: 100,
minValue: 30,
maxValue: 70
}
},
methods: {
updateMin(e) {
this.minValue = Math.min(e.target.value, this.maxValue)
},
updateMax(e) {
this.maxValue = Math.max(e.target.value, this.minValue)
}
}
}
</script>
<style>
.range-slider {
width: 300px;
margin: 20px;
}
input[type="range"] {
width: 100%;
margin: 10px 0;
}
</style>
使用第三方库 vue-slider-component
对于更复杂的需求,推荐使用专门的滑块组件库。vue-slider-component 是一个功能丰富的 Vue 滑块组件。
安装依赖:
npm install vue-slider-component --save
基本用法:
<template>
<div>
<vue-slider
v-model="value"
:min="0"
:max="100"
:interval="10"
:drag-on-click="true"
:tooltip="'always'"
:marks="marks"
/>
</div>
</template>
<script>
import VueSlider from 'vue-slider-component'
import 'vue-slider-component/theme/default.css'
export default {
components: {
VueSlider
},
data() {
return {
value: [20, 80],
marks: [
{ label: '0', value: 0 },
{ label: '50', value: 50 },
{ label: '100', value: 100 }
]
}
}
}
</script>
自定义滑块组件
如果需要完全自定义样式和行为,可以创建自己的滑块组件。
<template>
<div class="custom-slider">
<div class="slider-track">
<div
class="slider-range"
:style="rangeStyle"
></div>
<div
class="slider-thumb left-thumb"
:style="leftThumbStyle"
@mousedown="startDrag('left')"
></div>
<div
class="slider-thumb right-thumb"
:style="rightThumbStyle"
@mousedown="startDrag('right')"
></div>
</div>
</div>
</template>
<script>
export default {
props: {
min: { type: Number, default: 0 },
max: { type: Number, default: 100 },
value: { type: Array, default: () => [30, 70] }
},
data() {
return {
activeThumb: null,
currentValue: [...this.value]
}
},
computed: {
rangeStyle() {
const left = ((this.currentValue[0] - this.min) / (this.max - this.min)) * 100
const right = 100 - ((this.currentValue[1] - this.min) / (this.max - this.min)) * 100
return {
left: `${left}%`,
right: `${right}%`
}
},
leftThumbStyle() {
return {
left: `${((this.currentValue[0] - this.min) / (this.max - this.min)) * 100}%`
}
},
rightThumbStyle() {
return {
left: `${((this.currentValue[1] - this.min) / (this.max - this.min)) * 100}%`
}
}
},
methods: {
startDrag(thumb) {
this.activeThumb = thumb
document.addEventListener('mousemove', this.handleDrag)
document.addEventListener('mouseup', this.stopDrag)
},
handleDrag(e) {
if (!this.activeThumb) return
const slider = this.$el.querySelector('.slider-track')
const rect = slider.getBoundingClientRect()
let position = (e.clientX - rect.left) / rect.width
position = Math.max(0, Math.min(1, position))
const value = Math.round(position * (this.max - this.min) + this.min)
if (this.activeThumb === 'left') {
this.currentValue[0] = Math.min(value, this.currentValue[1])
} else {
this.currentValue[1] = Math.max(value, this.currentValue[0])
}
this.$emit('input', [...this.currentValue])
},
stopDrag() {
this.activeThumb = null
document.removeEventListener('mousemove', this.handleDrag)
document.removeEventListener('mouseup', this.stopDrag)
}
}
}
</script>
<style>
.custom-slider {
width: 300px;
margin: 20px;
}
.slider-track {
position: relative;
height: 4px;
background: #ddd;
border-radius: 2px;
}
.slider-range {
position: absolute;
height: 100%;
background: #42b983;
border-radius: 2px;
}
.slider-thumb {
position: absolute;
width: 16px;
height: 16px;
background: #fff;
border: 2px solid #42b983;
border-radius: 50%;
top: -6px;
transform: translateX(-50%);
cursor: pointer;
}
</style>
响应式设计考虑
确保滑块在不同设备上都能良好工作,可以添加响应式样式:
@media (max-width: 768px) {
.custom-slider {
width: 100%;
padding: 0 10px;
}
.slider-thumb {
width: 24px;
height: 24px;
top: -10px;
}
}
无障碍访问
为提升可访问性,可以添加 ARIA 属性:
<div
class="slider-thumb left-thumb"
role="slider"
aria-valuemin="min"
aria-valuemax="max"
aria-valuenow="currentValue[0]"
tabindex="0"
></div>
这些方法提供了从简单到复杂的 Vue 滑块区间实现方案,可以根据项目需求选择合适的方式。







