ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Vuetify v-rating 星级评分组件完全指南:从基础用法到源码级原理

Vuetify v-rating 星级评分组件完全指南:从基础用法到源码级原理 Vuetify v-rating 星级评分组件完全指南从基础用法到源码级原理【免费下载链接】vuetify Vue Component Framework项目地址: https://gitcode.com/gh_mirrors/vu/vuetifyv-rating是 Vuetify 中用于收集用户评分的专业组件它以星形图标为交互载体将用户反馈这一简单指标转化为直观、可无障碍访问的界面元素广泛应用于电商评价、产品满意度调查、内容打分等场景。本文以 Vuetify 官方文档的 Ratings 页面为主体结合本仓库packages/vuetify/src/components/VRating/下的源码实现与测试用例系统讲解v-rating的全部核心配置项颜色、密度、清空、只读、悬停、图标、半星增量、尺寸、无障碍标签、两个插槽item、item-label的进阶用法以及它背后的状态计算、键盘导航和 CSS 半星裁剪原理让你既能会用也能懂它为什么这么工作。组件定位与核心价值v-rating是构建用户控件时一个专门但重要的部件。通过评分收集用户反馈是一种简单的分析手段却能为你的产品或应用提供大量有价值的信息。它本质上是一个被视觉化包装的单选控件——从源码看每个评分项在内部渲染为一个隐藏的input typeradio见 VRating.tsx这保证了它在不依赖 JavaScript 的情况下依然具备原生表单语义也决定了它与v-form、v-model等机制的自然融合。从组件构成上看VRating复用了多个 Vuetify 基础组件与组合式函数每个星形图标实际由VBtn渲染VRating.tsx因此天然继承了按钮的尺寸、密度、涟漪ripple等能力密度与尺寸分别来自makeDensityProps与makeSizePropsVRating.tsx与 Vuetify 全局约定保持一致主题支持通过makeThemeProps与provideTheme接入VRating.tsx。基础用法v-rating提供了一个简单直观的接口来收集用户反馈。最基本的使用方式只需绑定v-modeltemplate div classtext-center v-rating v-modelrating/v-rating /div /template script setup import { ref } from vue const rating ref(3) /script默认渲染 5 颗星v-model的值为数值型评分。在官方文档的交互示例usage.vue中你还可以实时切换half-increments、hover、readonly、length、size、color、active-color等配置来观察组件行为并把生成的代码直接复制到你的项目中。从源码角度理解这个简单接口背后的逻辑值规范化normalizedValue通过clamp(parseFloat(rating.value), 0, Number(props.length))把任意输入钳制在0 ~ length区间VRating.tsx即使你传入越界值也不会渲染出错状态计算itemState依据当前值 星值判断每颗星是否填充isFilled并据此决定使用fullIcon还是emptyIconVRating.tsx事件绑定eventState为每个评分档位生成onMouseenter、onMouseleave、onClick处理器其中点击回调会在disabled或readonly时直接短路返回VRating.tsx。对应地浏览器端测试 VRating.spec.browser.tsx 验证了点击第 4 个评分项后v-model值变为 4响应v-model外部变化重新渲染图标等基础行为。API 一览v-rating是评分功能的唯一核心组件其全部 props、slots 与事件在 VRating.tsx 中集中定义。下表汇总了所有可用配置项| Prop | 类型 | 默认值 | 说明 | | - | - | - | - | |model-value|number \| string|0| 当前评分值支持v-model双向绑定 | |length|number \| string|5| 评分项星星的数量 | |color|string| — | 未选中/填充项的基础颜色 | |active-color|string| — | 已填充项的颜色未设置时回退到color| |clearable|boolean|false| 点击当前评分值可将其重置为0| |readonly|boolean|false| 只读模式禁止修改评分 | |disabled|boolean|false| 禁用整个组件 | |hover|boolean|false| 悬停时图标变为实心并略微放大 | |half-increments|boolean|false| 支持0.5粒度评分 | |item-labels|string[]| — | 每个评分项的标签文本数组 | |item-label-position|top \| bottom|top| 标签显示在图标上方或下方 | |empty-icon|IconValue|$ratingEmpty| 未填充状态使用的图标 | |full-icon|IconValue|$ratingFull| 已填充状态使用的图标 | |item-aria-label|string|$vuetify.rating.ariaLabel.item| 供辅助技术使用的每项无障碍标签 | |ripple|boolean|false| 点击时是否显示涟漪效果 | |name|string| 自动生成 | 内部 radio 输入框的name属性 |组件还会自动继承density、size、tag、theme以及通用组件属性class/style等。事件方面仅有一个update:model-valueVRating.tsx用于配合v-model。其中两个图标默认值$ratingEmpty与$ratingFull是 Vuetify 主题中注册的图标别名会跟随当前图标的默认集如 Material Design Icons解析为具体图标你也可以用任意自定义图标覆盖。Props 实战详解颜色Colorv-rating的颜色可以随心定制选中与未选中状态的颜色可以分别设置active-color控制已填充星星的颜色color控制未填充星星以及作为其回退色的颜色。template div classtext-center v-rating v-modelrating active-colorblue colororange-lighten-1 /v-rating /div /template script setup import { ref } from vue const rating ref(3) /script在源码中activeColor props.activeColor ?? props.color而每颗星的实际颜色由(isFilled || isHovered) ? activeColor : props.color决定VRating.tsx——即填充状态和悬停状态都使用active-color。完整的官方示例见 prop-color.vue。密度Density使用densityprop 控制v-rating各项在垂直方向占用的空间可选值default、comfortable、compacttemplate div classd-flex flex-column align-center justify-center v-rating v-modelrating classma-2 densitydefault/v-rating v-rating v-modelrating classma-2 densitycomfortable/v-rating v-rating v-modelrating classma-2 densitycompact/v-rating /div /template该 prop 直接透传给内部每个VBtnVRating.tsx因此密度的视觉表现与 Vuetify 其他组件保持一致。完整示例见 prop-density.vue。清空Clearable点击当前评分值可以将评分重置为0template div classtext-center v-rating v-modelrating clearable/v-rating /div /template script setup import { ref } from vue const rating ref(3) /script其实现逻辑一行即可说明rating.value normalizedValue.value value props.clearable ? 0 : valueVRating.tsx——当再次点击当前值且开启了clearable时归零否则设置为新值。测试用例 VRating.spec.browser.tsx 验证了未开启时点击已选值不变化、开启后点击同一项归零的完整行为。只读Readonly对于不允许修改的评分展示如只读的商品平均分使用readonlyproptemplate div classtext-center v-rating v-modelrating readonly/v-rating /div /template源码中readonly与disabled会在点击与键盘事件处理器中直接返回VRating.tsx 与 L157同时根元素会加上v-rating--readonly类。样式层通过.v-rating--readonly { pointer-events: none }直接屏蔽所有指针交互VRating.sass实现双重防护。测试用例分别验证了只读状态下点击与方向键都不会改变值VRating.spec.browser.tsx。悬停效果Hover使用hoverprop 后鼠标悬停到的评分图标会变为实心颜色并略微放大template div classtext-center v-rating v-modelrating hover/v-rating /div /template放大效果来自样式层悬停时.v-rating--hover作用域下的按钮应用transform缩放VRating.sass该 transform 值定义在 _variables.scss 中。悬停状态由hoverIndex追踪鼠标进入某个档位时记录下标离开时重置为-1VRating.tsx。测试 VRating.spec.browser.tsx 通过userEvent.hover验证了悬停第 3 个图标后前 3 个图标全部变为实心。标签Labelsv-rating可以在每个评分项的上方或下方显示标签通过item-label-position控制位置默认toptemplate div classd-flex align-center justify-center flex-column v-rating v-modelrating :item-labels[sad, , , , happy] classma-2 item-label-positiontop /v-rating v-rating v-modelrating :item-labels[sad, , , , happy] classma-2 item-label-positionbottom /v-rating /div /templateitem-labels是长度与length对应的字符串数组空字符串会渲染为占位空格以保持对齐VRating.tsx。完整示例见 prop-item-labels.vue。在showcase测试故事中也有对应演示VRating.spec.browser.tsx。图标Icons可以使用自定义图标来替换默认的星形。图标由三个 prop 控制empty-icon未填充、full-icon已填充配合half-increments时半星图标通过 CSS 裁剪实现见下文半星增量因此并不需要一个单独的half-iconproptemplate div classtext-center v-rating v-modelrating empty-iconmdi-circle-outline full-iconmdi-circle half-increments hover /v-rating /div /template图标值支持 Vuetify 的IconValue类型即可以是图标名字符串也可以是渲染函数或 SVG 组件VRating.tsx。完整示例见 prop-icons.vue。数量Length通过lengthprop 改变评分项的数量template div classtext-center v-rating v-modelrating length10/v-rating /div /template源码中使用createRange(Number(props.length), 1)生成从 1 到 length 的序列VRating.tsx配合normalizedValue的钳制逻辑length 也可以在运行时动态变化。示例见 prop-length.vue。半星增量Half incrementshalf-incrementsprop 提升了评分粒度允许出现.5这样的值template div classtext-center v-rating v-modelrating half-increments hover /v-rating pre{{ rating }}/pre /div /template它的实现非常巧妙值得展开说明档位翻倍increments会把每个整数档位展开为[v - 0.5, v]例如 5 颗星会生成 10 个可点击档位VRating.tsx。测试断言此时页面上出现 10 个隐藏 radio 输入框VRating.spec.browser.tsxCSS 裁剪绘制半星半星档位渲染时带有v-rating__item--half类样式层使用clip-path: polygon(0 0, 50% 0, 50% 100%, 0 100%)只显示图标左半部分并配合绝对定位叠加在整星之上VRating.sass从而在视觉上呈现左实右空的半星效果键盘步进方向键的步长会随halfIncrements变为0.5VRating.tsx。测试验证点击第 4 个半星档位得到3.5分VRating.spec.browser.tsx。完整示例见 prop-half-increments.vue。尺寸Sizesizeprop 用于控制图标大小可以复用v-icon的尺寸值也可以传入任意数值v-rating v-modelrating size64/v-ratingsize来自makeSizeProps并直接透传给内部每个VBtnVRating.tsx。测试用例专门验证了half-increments与自定义size64组合使用时的行为VRating.spec.browser.tsx。官方交互示例 usage.vue 中可拖动滑块在 16~128 之间实时预览尺寸变化。无障碍标签Aria Label通过item-aria-labelprop 为每个评分项提供辅助技术屏幕阅读器可读的标签v-rating v-modelrating :item-aria-label(value) Rate ${value} out of 5 /v-rating默认值为$vuetify.rating.ariaLabel.item一个本地化文案键。源码中该标签会同时渲染在隐藏文本v-rating__hidden中并作为每个VBtn的aria-labelVRating.tsx 与 L217确保辅助技术与普通用户获得一致的信息。文案通过useLocale的t函数按当前语言解析。Slots 深度定制插槽为评分组件提供了高级定制能力让你完全掌控评分的展示形式。Item 插槽item插槽允许你完全替换每个评分项的默认渲染内容。插槽接收以下属性value当前项的值index当前项的索引isFilled该项是否处于填充状态isHovered该项是否处于悬停状态icon当前应显示的图标color/activeColor颜色信息props透传给内部VBtn的完整按钮属性含键盘与无障碍处理rating当前总分template div classtext-center v-rating v-modelrating template v-slot:itemprops v-icon :colorprops.isFilled ? colors[props.index] : grey-lighten-1 sizelarge {{ props.isFilled ? mdi-star-circle : mdi-star-circle-outline }} /v-icon /template /v-rating /div /template script setup import { ref } from vue const colors [green, purple, orange, indigo, red] const rating ref(4.5) /script该示例让每颗填充的星星使用不同的颜色。注意插槽内容默认仍然包裹在带点击/悬停/键盘事件的label中评分交互依然生效props中还携带了tabindex与键盘处理器供自定义按钮使用VRating.tsx。完整示例见 slot-item.vueshowcase故事中也有一个用VBtn渲染数字评分的变体VRating.spec.browser.tsx。自定义标签插槽item-labelitem-label插槽让你在评分项旁展示任意内容。插槽接收{ value, index, label }属性其中label来自item-labels数组中的对应项template v-rating v-modelrating template v-slot:item-labelprops C{{ props.value }} /template /v-rating /template当该插槽存在时它会优先生效并覆盖item-labels数组的默认渲染VRating.tsx。测试中的展示故事将标签渲染为C1、C2等形式VRating.spec.browser.tsx示例文件见 slot-item-label.vue。进阶场景卡片评分评分组件非常适合与产品类界面搭配用于收集和展示客户反馈。官方文档提供了两个组合示例misc-card.vue将v-rating嵌入v-card结合v-avatar、v-list等组件展示单条用户评价misc-card-overview.vue卡片式评分总览。这类场景通常还会配合readonly仅展示已有评分或clearable允许修改并可参考 cards 与 icons 文档组合出更丰富的界面。文档中原本规划的 Advanced usage 示例misc-advanced.vue见 ratings.md 中的注释目前仍处于注释状态尚未正式开放。键盘导航与无障碍设计v-rating提供了完整的键盘操作支持这也是它作为表单控件的重要一环Tab 聚焦当前评分值对应的项拥有tabindex0其余项为-1确保只聚焦一个锚点VRating.tsx方向键调节ArrowRight增加值上限为lengthArrowLeft减少值下限为 0步长为 1 或半星模式下的 0.5调节后焦点会跟随移动到新的当前项VRating.tsx空格选中VBtn自身的按钮语义天然支持空格触发点击隐藏 radio 语义每个档位对应一个隐藏的 radio 输入配合name属性构成标准的单选组name未指定时自动生成v-rating-{uid}VRating.tsx。浏览器测试 VRating.spec.browser.tsx 完整覆盖了Tab 进入 → 空格评分 → Tab 离开 → ShiftTab 返回 → 方向键调节并移动焦点的整条键盘链路。样式体系速览v-rating的样式集中在 VRating.sass 与 _variables.scss 中几个关键设计点根元素为display: inline-flex且max-width: 100%可随内容自适应每个评分项外包一层v-rating__wrapper标签在顶部或底部时分别使用flex-direction: column与column-reverse实现上下布局内部按钮为plain变体并设置较低不透明度填充/悬停时通过图标切换与transform缩放表达状态半星通过clip-path裁剪叠加实现只读时以pointer-events: none禁用指针交互。总结v-rating是 Vuetify 中一个小而精的组件通过v-model与length、color/active-color、clearable、readonly、hover、half-increments、size、item-labels、自定义图标与无障碍标签等十余个配置项即可覆盖从简单的五星打分到带半星、自定义图标、逐项标签和完全自定义渲染的复杂评分场景。其底层以隐藏 radio 输入 VBtn图标按钮 CSS 裁剪半星的组合实现兼顾了表单语义、无障碍访问与视觉表现力相关实现细节均可在 VRating.tsx、VRating.sass 与 VRating.spec.browser.tsx 中进一步查阅。配合卡片、图标等组件组合使用即可快速构建专业的产品反馈界面。【免费下载链接】vuetify Vue Component Framework项目地址: https://gitcode.com/gh_mirrors/vu/vuetify创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进