vue滑动评分实现
实现滑动评分功能
在Vue中实现滑动评分功能可以通过自定义组件结合触摸或鼠标事件完成。以下是两种常见实现方式:

基于自定义滑块组件
创建一个可拖动的评分滑块,利用v-model实现双向绑定:

<template>
<div class="rating-slider">
<div class="track" ref="track" @mousemove="handleMove" @click="updateRating">
<div class="thumb" :style="{ left: thumbPosition }"
@mousedown="startDrag" @touchstart="startDrag"></div>
</div>
<span>当前评分: {{ currentRating }}</span>
</div>
</template>
<script>
export default {
props: {
value: { type: Number, default: 0 },
max: { type: Number, default: 5 }
},
data() {
return {
isDragging: false,
currentRating: this.value
}
},
computed: {
thumbPosition() {
return `${(this.currentRating / this.max) * 100}%`
}
},
methods: {
startDrag(e) {
this.isDragging = true
if (e.type === 'touchstart') {
document.addEventListener('touchmove', this.handleMove)
document.addEventListener('touchend', this.stopDrag)
} else {
document.addEventListener('mousemove', this.handleMove)
document.addEventListener('mouseup', this.stopDrag)
}
},
handleMove(e) {
if (!this.isDragging) return
const track = this.$refs.track
const rect = track.getBoundingClientRect()
const clientX = e.clientX || e.touches[0].clientX
let pos = (clientX - rect.left) / rect.width
pos = Math.max(0, Math.min(1, pos))
this.currentRating = Math.round(pos * this.max * 10) / 10
},
stopDrag() {
this.isDragging = false
document.removeEventListener('mousemove', this.handleMove)
document.removeEventListener('touchmove', this.handleMove)
this.$emit('input', this.currentRating)
},
updateRating(e) {
this.handleMove(e)
this.stopDrag()
}
}
}
</script>
<style>
.rating-slider {
width: 300px;
margin: 20px;
}
.track {
height: 10px;
background: #eee;
border-radius: 5px;
position: relative;
cursor: pointer;
}
.thumb {
width: 20px;
height: 20px;
background: #42b983;
border-radius: 50%;
position: absolute;
top: -5px;
transform: translateX(-50%);
}
</style>
基于现有UI库
使用现成的Vue UI库可以快速实现评分功能,例如:
<template>
<div>
<!-- 使用Element UI的滑块 -->
<el-slider v-model="rating" :max="5" :step="0.5" show-stops></el-slider>
<!-- 或使用Vuetify的评分组件 -->
<v-rating v-model="rating" half-increments hover></v-rating>
</div>
</template>
<script>
export default {
data() {
return {
rating: 3.5
}
}
}
</script>
实现星形评分组件
创建一个视觉上更直观的星形评分组件:
<template>
<div class="star-rating">
<span v-for="star in maxStars" :key="star"
@click="setRating(star)" @mouseover="hoverRating = star"
@mouseleave="hoverRating = 0"
:class="{ 'active': star <= currentRating }">★</span>
</div>
</template>
<script>
export default {
props: {
value: { type: Number, default: 0 },
maxStars: { type: Number, default: 5 }
},
data() {
return {
currentRating: this.value,
hoverRating: 0
}
},
methods: {
setRating(star) {
this.currentRating = star
this.$emit('input', star)
}
},
watch: {
value(newVal) {
this.currentRating = newVal
}
}
}
</script>
<style>
.star-rating span {
font-size: 24px;
color: #ccc;
cursor: pointer;
transition: color 0.2s;
}
.star-rating span.active {
color: #ffd700;
}
.star-rating span:hover {
color: #ffd700;
}
</style>
注意事项
- 移动端适配需要考虑触摸事件处理
- 可以通过CSS变量自定义颜色和大小
- 半星评分可以通过计算小数部分实现
- 性能优化时可考虑使用
requestAnimationFrame处理拖动事件 - 无障碍访问需要添加适当的ARIA属性
以上实现方式可根据具体需求选择或组合使用,自定义组件方式灵活性更高,而UI库组件可以快速集成但定制性有限。






