StarRating

View source
交互式星级评分组件。

简介

MStarRating 是一个功能丰富的星级评分组件。支持整星与半星评分、只读展示、自定义星级总数与图标、键盘交互,并提供徽章展示与高亮聚焦态等增强能力。

基于 Nuxt UI 的 Button 与 Badge 组件构建

用法

默认 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 评分图标

emptyIconfilledIconhalfIcon 可整体替换为其他图标,配合 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:modelValuechangehover

当前评分: 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
max5number

最大星级数

emptyIcon'i-lucide-star'any

未选中星星的图标

filledIcon'i-lucide-star'any

选中星星的图标

halfIcon'i-lucide-star-half'any

半星图标

idstring
namestring
buttonPropsButtonProps
color"primary" | "secondary" | "info" | "success" | "warning" | "error" | "important" | "neutral"

选中星星的颜色

size'md'"xs" | "sm" | "md" | "lg" | "xl"

星星大小

modelValue0number
showBadgetrueboolean

是否显示评分徽章

disabledboolean

是否禁用

highlightboolean

Highlight the ring color like a focus state.

readonlyboolean

是否只读

allowHalfboolean

是否允许半星

clearableboolean

是否允许清除评分

uiRecord<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
Copyright © 2025 - 2026 YiXuan - MIT License