vue滑块实现
Vue 滑块实现方法
使用原生HTML5 range input
通过HTML5的<input type="range">实现基础滑块功能:
<template>
<div>
<input
type="range"
min="0"
max="100"
v-model="sliderValue"
@input="handleInput"
>
<p>当前值: {{ sliderValue }}</p>
</div>
</template>
<script>
export default {
data() {
return {
sliderValue: 50
}
},
methods: {
handleInput(event) {
console.log('当前值:', event.target.value)
}
}
}
</script>
使用第三方组件库
Element UI的滑块组件实现:

<template>
<el-slider v-model="value" :min="0" :max="100"></el-slider>
</template>
<script>
import { ElSlider } from 'element-plus'
export default {
components: {
ElSlider
},
data() {
return {
value: 30
}
}
}
</script>
自定义滑块组件
创建可复用的自定义滑块组件:

<!-- Slider.vue -->
<template>
<div class="custom-slider">
<div
class="slider-track"
ref="track"
@click="handleTrackClick"
>
<div
class="slider-thumb"
:style="{ left: thumbPosition + 'px' }"
@mousedown="startDrag"
></div>
</div>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number,
default: 0
},
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 100
}
},
data() {
return {
isDragging: false,
trackWidth: 0
}
},
computed: {
thumbPosition() {
return (this.value - this.min) / (this.max - this.min) * this.trackWidth
}
},
mounted() {
this.trackWidth = this.$refs.track.offsetWidth
window.addEventListener('resize', this.updateTrackWidth)
},
beforeDestroy() {
window.removeEventListener('resize', this.updateTrackWidth)
},
methods: {
updateTrackWidth() {
this.trackWidth = this.$refs.track.offsetWidth
},
startDrag() {
this.isDragging = true
document.addEventListener('mousemove', this.handleDrag)
document.addEventListener('mouseup', this.stopDrag)
},
handleDrag(e) {
if (!this.isDragging) return
const rect = this.$refs.track.getBoundingClientRect()
let newValue = (e.clientX - rect.left) / this.trackWidth
newValue = Math.max(0, Math.min(1, newValue))
this.$emit('input', Math.round(this.min + newValue * (this.max - this.min)))
},
stopDrag() {
this.isDragging = false
document.removeEventListener('mousemove', this.handleDrag)
document.removeEventListener('mouseup', this.stopDrag)
},
handleTrackClick(e) {
const rect = this.$refs.track.getBoundingClientRect()
const newValue = (e.clientX - rect.left) / this.trackWidth
this.$emit('input', Math.round(this.min + newValue * (this.max - this.min)))
}
}
}
</script>
<style>
.custom-slider {
width: 100%;
padding: 15px 0;
}
.slider-track {
position: relative;
width: 100%;
height: 4px;
background: #ddd;
border-radius: 2px;
cursor: pointer;
}
.slider-thumb {
position: absolute;
width: 16px;
height: 16px;
background: #409eff;
border-radius: 50%;
transform: translateX(-50%);
cursor: grab;
}
.slider-thumb:active {
cursor: grabbing;
}
</style>
双向绑定与事件处理
实现更复杂的交互逻辑:
<template>
<div>
<input
type="range"
v-model.number="internalValue"
:min="min"
:max="max"
:step="step"
@input="onInput"
@change="onChange"
>
<input
type="number"
v-model.number="internalValue"
:min="min"
:max="max"
:step="step"
@change="onNumberChange"
>
</div>
</template>
<script>
export default {
props: {
value: {
type: Number,
required: true
},
min: {
type: Number,
default: 0
},
max: {
type: Number,
default: 100
},
step: {
type: Number,
default: 1
}
},
data() {
return {
internalValue: this.value
}
},
watch: {
value(newVal) {
this.internalValue = newVal
}
},
methods: {
onInput() {
this.$emit('input', this.internalValue)
},
onChange() {
this.$emit('change', this.internalValue)
},
onNumberChange() {
this.internalValue = Math.max(this.min, Math.min(this.max, this.internalValue))
this.$emit('input', this.internalValue)
this.$emit('change', this.internalValue)
}
}
}
</script>
垂直滑块实现
通过CSS transform实现垂直方向滑块:
<template>
<div class="vertical-slider-container">
<input
type="range"
v-model="value"
orient="vertical"
class="vertical-slider"
min="0"
max="100"
>
</div>
</template>
<script>
export default {
data() {
return {
value: 50
}
}
}
</script>
<style>
.vertical-slider-container {
height: 200px;
padding: 0 20px;
}
.vertical-slider {
width: 200px;
height: 20px;
transform: rotate(-90deg);
transform-origin: 100px 100px;
}
</style>






