Vue星级评分组件实现:点击指定星级同步选中前置星级
Vue星级评分组件实现方案
要实现点击第n颗星时,前n颗星全部高亮的效果,这里提供两种简洁的实现方式,推荐第一种更易维护的方案:
方案一:单状态变量控制(推荐)
这种方式不需要给每个星级单独维护isClicked状态,只用一个变量记录当前选中的星级,通过计算判断样式:
- 修改数据与状态
移除每个星级对象中的isClicked,新增一个响应式变量记录当前选中值:
import { ref } from 'vue'; const currentRating = ref(0); const ratingsArray = [ { name: 'rating1', ratingCount: 1 }, { name: 'rating2', ratingCount: 2 }, { name: 'rating3', ratingCount: 3 }, { name: 'rating4', ratingCount: 4 }, { name: 'rating5', ratingCount: 5 }, ];
- 编写点击处理函数
点击星级时,判断是否是当前已选中的星级,决定是设置选中还是取消所有:
function handleRatingClick(selectedCount) { if (currentRating.value === selectedCount) { // 再次点击已选中的最高星级,取消所有高亮 currentRating.value = 0; } else { // 设置选中到当前点击的星级 currentRating.value = selectedCount; } }
- 更新模板
通过currentRating与星级的ratingCount比较,动态绑定样式:
<template> <div v-for="rating in ratingsArray" :key="rating.name" @click="handleRatingClick(rating.ratingCount)" :class="rating.ratingCount <= currentRating.value ? 'ratingBoxFilled' : 'ratingBox'" > </div> </template>
方案二:保留原数组结构修改
如果要保留原有的isClicked结构,可以修改点击函数,遍历数组更新状态:
- 修改点击函数
传入当前星级对象,根据其ratingCount批量更新所有星级的状态:
function toggleClick(selectedRating) { const targetCount = selectedRating.ratingCount; // 判断当前是否已经选中到该星级 const isAlreadyActive = selectedRating.isClicked.value && ratingsArray.every(r => r.ratingCount <= targetCount ? r.isClicked.value : !r.isClicked.value); if (isAlreadyActive) { // 取消所有星级的选中状态 ratingsArray.forEach(r => r.isClicked.value = false); } else { // 将小于等于目标星级的设为选中,其余设为未选中 ratingsArray.forEach(r => { r.isClicked.value = r.ratingCount <= targetCount; }); } }
- 更新模板绑定
点击时传入当前星级对象:
<template> <div v-for="rating in ratingsArray" :key="rating.name" @click="toggleClick(rating)" :class="rating.isClicked.value ? 'ratingBoxFilled' : 'ratingBox'" > </div> </template>
两种方案都能实现你要的效果,方案一的代码更简洁,状态维护成本更低,推荐使用。
内容的提问来源于stack exchange,提问作者mikasa
相关产品推荐
相关产品推荐

