vue实现星级评分效果
实现星级评分的基本思路
在Vue中实现星级评分效果,通常需要以下几个核心功能:渲染星星图标、处理点击交互、支持半星评分、显示当前评分等。可以通过组件化方式封装,便于复用。
使用Font Awesome图标库
安装Font Awesome库:
npm install @fortawesome/fontawesome-svg-core @fortawesome/free-solid-svg-icons @fortawesome/vue-fontawesome
组件代码示例:
<template>
<div class="star-rating">
<font-awesome-icon
v-for="(star, index) in stars"
:key="index"
:icon="star.icon"
:class="{ 'active': star.active }"
@click="rate(index + 1)"
@mouseover="hover(index + 1)"
@mouseleave="resetHover"
/>
<span v-if="showRating">{{ currentRating }}/{{ maxStars }}</span>
</div>
</template>
<script>
import { ref, computed } from 'vue'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { faStar, faStarHalfAlt } from '@fortawesome/free-solid-svg-icons'
export default {
components: { FontAwesomeIcon },
props: {
maxStars: { type: Number, default: 5 },
initialRating: { type: Number, default: 0 },
showRating: { type: Boolean, default: true }
},
setup(props) {
const currentRating = ref(props.initialRating)
const hoverRating = ref(0)
const stars = computed(() => {
return Array.from({ length: props.maxStars }, (_, i) => {
const rating = hoverRating.value || currentRating.value
return {
icon: rating >= i + 1 ? faStar : faStarHalfAlt,
active: rating >= i + 1
}
})
})
const rate = (rating) => {
currentRating.value = rating
}
const hover = (rating) => {
hoverRating.value = rating
}
const resetHover = () => {
hoverRating.value = 0
}
return { stars, currentRating, rate, hover, resetHover }
}
}
</script>
<style>
.star-rating {
display: inline-flex;
align-items: center;
}
.star-rating svg {
color: #ddd;
cursor: pointer;
margin: 0 2px;
}
.star-rating svg.active {
color: #ffc107;
}
.star-rating span {
margin-left: 8px;
}
</style>
使用纯CSS实现星星样式
不需要依赖图标库的纯CSS实现方案:
<template>
<div class="star-rating">
<span
v-for="(star, index) in stars"
:key="index"
class="star"
:class="{ 'filled': star.filled, 'half': star.half }"
@click="setRating(index + 1)"
@mouseover="hoverRating = index + 1"
@mouseleave="hoverRating = 0"
>★</span>
</div>
</template>
<script>
import { ref, computed } from 'vue'
export default {
props: {
maxStars: { type: Number, default: 5 },
rating: { type: Number, default: 0 }
},
setup(props) {
const hoverRating = ref(0)
const internalRating = ref(props.rating)
const stars = computed(() => {
const activeRating = hoverRating.value || internalRating.value
return Array.from({ length: props.maxStars }, (_, i) => {
const starValue = i + 1
return {
filled: starValue <= activeRating,
half: starValue - 0.5 === activeRating
}
})
})
const setRating = (rating) => {
internalRating.value = rating
}
return { stars, hoverRating, setRating }
}
}
</script>
<style>
.star-rating {
unicode-bidi: bidi-override;
direction: rtl;
text-align: center;
}
.star-rating .star {
font-size: 24px;
color: #ddd;
cursor: pointer;
display: inline-block;
}
.star-rating .star:hover,
.star-rating .star.filled {
color: #ffc107;
}
.star-rating .star.half {
position: relative;
}
.star-rating .star.half:before {
content: '★';
position: absolute;
left: 0;
width: 50%;
overflow: hidden;
color: #ffc107;
}
</style>
支持半星评分的实现
在点击事件处理中添加半星判断逻辑:

const setRating = (index, event) => {
const star = event.target.getBoundingClientRect()
const clickX = event.clientX - star.left
internalRating.value = clickX < star.width / 2 ? index - 0.5 : index
}
可配置的星星大小和颜色
通过props传递配置参数:
props: {
starSize: { type: String, default: '24px' },
activeColor: { type: String, default: '#ffc107' },
inactiveColor: { type: String, default: '#ddd' }
}
在模板中使用动态样式:
<span
class="star"
:style="{
fontSize: starSize,
color: star.filled ? activeColor : inactiveColor
}"
>
禁用状态的评分组件
添加disabled属性控制交互:

props: {
disabled: { type: Boolean, default: false }
}
在模板中根据状态禁用事件:
<span
@click="!disabled && setRating(index + 1)"
@mouseover="!disabled && (hoverRating = index + 1)"
>
双向绑定实现
使用v-model实现双向数据绑定:
const emit = defineEmits(['update:rating'])
const setRating = (rating) => {
internalRating.value = rating
emit('update:rating', rating)
}
父组件使用方式:
<star-rating v-model="productRating" />
动画效果增强
添加CSS过渡效果使交互更流畅:
.star {
transition: all 0.2s ease-in-out;
}
.star:hover {
transform: scale(1.2);
}
以上方案提供了从简单到复杂的多种实现方式,可根据项目需求选择合适的方案。组件化的实现便于在不同项目中复用,而配置化的设计则增加了灵活性。






