StarRating
交互式星级评分组件。
简介
MStarRating 是一个功能丰富的星级评分组件。支持整星与半星评分、只读展示、自定义星级总数与图标、键盘交互,并提供徽章展示与高亮聚焦态等增强能力。
用法
默认 5 星评分系统,点击星星写入 v-model:
3/5
<script setup lang="ts">
const value = ref(3)
</script>
<template>
<MStarRating v-model="value" />
</template>
allowHalf 半星评分
allowHalf 让每颗星可取半值,点击左右半区分别记为 .5 与整数评分:
3.5/5
<script setup lang="ts">
const value = ref(3.5)
</script>
<template>
<MStarRating v-model="value" allow-half />
</template>
clearable 可清除
clearable 允许再次点击当前值或按 Backspace 将评分清零,适合非必填场景:
2.5/5
<script setup lang="ts">
const value = ref(2.5)
</script>
<template>
<MStarRating v-model="value" allow-half clearable />
</template>
readonly 只读模式
readonly 仅展示评分并保留视觉,用于评价、评级等结果展示:
4/5
<script setup lang="ts">
const value = ref(4)
</script>
<template>
<MStarRating v-model="value" readonly />
</template>
max 星级总数
max 调整星星数量,可适配更细粒度的评分量表:
5/7
<script setup lang="ts">
const value = ref(5)
</script>
<template>
<MStarRating v-model="value" :max="7" />
</template>
emptyIcon 评分图标
emptyIcon、filledIcon、halfIcon 可整体替换为其他图标,配合 allowHalf 呈现半值形态:
2.5/5
<script setup lang="ts">
const value = ref(2.5)
</script>
<template>
<MStarRating
v-model="value"
allow-half
empty-icon="i-lucide-heart"
filled-icon="i-lucide-heart"
half-icon="i-lucide-heart-handshake"
/>
</template>
showBadge 评分徽章
showBadge 默认显示当前分值徽章,设为 false 后只保留星星本身:
<script setup lang="ts">
const value = ref(3)
</script>
<template>
<MStarRating v-model="value" :show-badge="false" />
</template>
color 颜色
color 指定选中星星与徽章颜色:
4/5
<script setup lang="ts">
const value = ref(4)
</script>
<template>
<MStarRating v-model="value" color="primary" />
</template>
highlight 高亮聚焦
highlight 为评分控件加上类聚焦的环形高亮,用于强调当前可操作项:
3/5
<script setup lang="ts">
const value = ref(3)
</script>
<template>
<MStarRating v-model="value" highlight />
</template>
buttonProps 按钮属性
buttonProps 透传到每颗星的按钮,可统一调整变体、内边距等底层样式:
3/5
<script setup lang="ts">
const value = ref(3)
</script>
<template>
<MStarRating v-model="value" :button-props="{ variant: 'soft', size: 'xs' }" />
</template>
disabled 禁用状态
disabled 同时阻止交互并降低不透明度:
4/5
<script setup lang="ts">
const value = ref(4)
</script>
<template>
<MStarRating v-model="value" disabled />
</template>
示例
继承字段上下文
放入 UFormField 后接收字段尺寸与错误态,评分图标随表单状态更新:
示例错误态
<template>
<UFormField label="满意度" size="xs" error="示例错误态">
<MStarRating />
</UFormField>
</template>
融入UFieldGroup
与重置按钮置于 UFieldGroup 时共享尺寸,适合在紧凑表单行内组合操作:
<template>
<UFieldGroup size="xs">
<MStarRating />
<UButton icon="i-lucide-rotate-ccw" color="neutral" variant="subtle" />
</UFieldGroup>
</template>
事件回调
点击、悬浮与键盘交互依次触发 update:modelValue、change 与 hover:
当前评分: 0
悬停星级: -
<script setup lang="ts">
const toast = useToast()
const rating = ref(0)
const hovering = ref<number | null>(null)
function handleChange(value: number) {
toast.add({
title: '评分已更改',
color: 'success',
description: `您选择的评分是 ${value} 星`
})
}
function handleHover(value: number | null) {
hovering.value = value
}
</script>
<template>
<div class="space-y-2">
<MStarRating v-model="rating" @change="handleChange" @hover="handleHover" />
<div class="text-sm text-gray-500">
<div>当前评分: {{ rating }}</div>
<div>悬停星级: {{ hovering ?? '-' }}</div>
</div>
</div>
</template>
自定义插槽
通过插槽添加前缀、后缀或自定义徽章:
评分:4/5 分 (128 评价)
<script setup lang="ts">
const rating = ref(4)
</script>
<template>
<MStarRating v-model="rating">
<template #prefix>
<span class="text-sm text-gray-500 mr-2">评分:</span>
</template>
<template #badge="{ label }">
<span class="text-sm text-primary font-semibold ml-2"> {{ label }} 分 </span>
</template>
<template #suffix>
<span class="text-xs text-gray-400 ml-2">(128 评价)</span>
</template>
</MStarRating>
</template>
键盘导航
组件支持完整的键盘交互,提升无障碍访问性:
- 方向键:
←→↑↓增减评分(支持半星步进) - 快捷键:
Home设置最小评分,End设置最大评分 - 数字键:
0-9直接跳转到对应评分 - 清除键:
Backspace/Delete清除评分(需启用clearable)
组件遵循 WCAG 无障碍规范,包含完整的 ARIA 属性和键盘焦点管理
API
Props
| Prop | Default | Type |
|---|---|---|
max | 5 | number最大星级数 |
emptyIcon | 'i-lucide-star' | any未选中星星的图标 |
filledIcon | 'i-lucide-star' | any选中星星的图标 |
halfIcon | 'i-lucide-star-half' | any半星图标 |
id | string | |
name | string | |
buttonProps | ButtonProps | |
color | "primary" | "secondary" | "info" | "success" | "warning" | "error" | "important" | "neutral"选中星星的颜色 | |
size | 'md' | "xs" | "sm" | "md" | "lg" | "xl"星星大小 |
modelValue | 0 | number |
showBadge | true | boolean是否显示评分徽章 |
disabled | boolean是否禁用 | |
highlight | booleanHighlight the ring color like a focus state. | |
readonly | boolean是否只读 | |
allowHalf | boolean是否允许半星 | |
clearable | boolean是否允许清除评分 | |
ui | Record<string, ClassNameValue> & { root?: SlotClass; stars?: SlotClass; star?: SlotClass; } |
Emits
| Event | Type |
|---|---|
update:modelValue | [value: number] |
change | [value: number] |
hover | [value: number] |
Slots
| Slot | Type |
|---|---|
prefix | { value: number; max: number; } |
badge | { value: number; max: number; label: string; } |
suffix | { value: number; max: number; } |
Theme
app.config.ts
export default defineAppConfig({
ui: {
starRating: {
slots: {
root: 'inline-flex items-center gap-1',
stars: 'flex items-center gap-0.5',
star: 'transition-all duration-150'
},
variants: {
interactive: {
true: {
star: 'cursor-pointer hover:scale-110'
}
},
disabled: {
true: {
star: 'cursor-not-allowed opacity-50'
}
},
readonly: {
true: {
star: 'cursor-default'
}
},
fieldGroup: {
horizontal: {
root: 'rounded-md bg-default ring ring-inset ring-accented px-1 not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]'
},
vertical: {
root: 'rounded-md bg-default ring ring-inset ring-accented px-1 not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
}
}
}
}
}
})
Changelog
No recent changes