3.22 Rate 评分

简介

评分组件 Rate 多用于展示评价或者对事物快速评级。本文将分析源码实现,耐心读完,相信会对您有所帮助。组件源码实现详见packages/rate/src/main.vue 。 🔗 组件文档 Rate 🔗 gitee源码 main.vue

更多组件剖析详见 👉 📚 Element 2 源码剖析组件总览

源码实现

组件的 prop 声明,各属性功能说明详见 官方文档rate#attributes

组件DOM结构

组件的根节点是类名el-rate的div元素,子元素包含评分icon图标和辅助文字两部分。

精简之后的结构代码如下:

<template>
  <div class="el-rate">
    <span v-for="(item, key) in max" class="el-rate__item">
      <i class="el-rate__icon"></i>
    </span>
    <span class="el-rate__text">{{ text }}</span>
  </div>
</template>

评分icon图标

组件的主要逻辑都在评分icon图标部分,接下来将采用渐进式的讲解方式,对比分析各代码功能逻辑。

基础展示

评分icon图标基于属性max渲染一个类名el-rate__itemspan元素列表生成。默认个数为 5。使用计算属性 classes 返回不同状态(选中/未选中)的 icon 类名。使用方法 getIconStyle 返回不同状态(选中/未选中)的 icon 颜色。

此时组件代码如下,没有鼠标交互事件,只能用作展示。

运行如下示例代码

image.png

组件支持评分分级,通过 iconClassescolorslowThresholdhighThreshold等属性控制显示逻辑内容。

评分默认被分为三个等级,可以利用颜色数组对分数及情感倾向进行分级(默认情况下不区分颜色)。三个等级所对应的颜色用colors属性设置,而它们对应的两个阈值则通过 low-thresholdhigh-threshold 设定。也可以通过传入颜色对象来自定义分段,键名为分段的界限值,键值为对应的颜色。

当组件用v-model传入了一个值, v-model的语法糖会把这个值当成propsvalue传到组件中。此时组件内部使用属性currentValue等同于属性value

⚠️ 当后面添加鼠标事件后,鼠标移动会直接改变 currentValue,属性currentValue不等同于属性value,

基础展示的样式计算

计算属性 classes基于组件的绑定值判断选中状态,生成的icon图标类名数组,由于遍历MAX是从1开始,所以调用时需item-1

方法getIconStyle 返回当前图标状态颜色。根据组件的只读状态,返回不同的未选中颜色。

计算属性activeClass使用方法getValueFromMap,返回对应分段区间的选中状态icon类名。

计算属性 classMap 返回 3 个分段区间对应颜色的对象。

  • iconClasses属性传入数组,共有 3 个元素,转换成对象,分段界限值基于lowThresholdhighThresholdmax,各区间为 [0,lowThreshold](lowThreshold,highThreshold)[highThreshold,max]

  • 若传入对象,可自定义分段,键名为分段的界限值,键值为对应的icon类名。

属性 iconClasses默认值 ['el-icon-star-on', 'el-icon-star-on', 'el-icon-star-on'],组件默认各评分层级 icon 类型相同。

计算属性 activeColor 基于同样的处理逻辑,返回对应分段区间的选中状态icon颜色。

计算属性voidClass根据是否只读状态,返回未选中状态icon类名。计算属性rateDisabled返回组件是否只读状态。

若表单禁用设置为 true,则表单内组件上的 disabled 属性不再生效。

支持半选

接下来在类名el-rate__iconi元素中添加一个类名el-rate__decimali元素,用于实现半选效果。

方法showDecimalIcon 控制组件支持半选展示状态。

  • 只读模式下,默认支持半选效果。

  • 非只读模式下,小数位要不小于0.5才会显示半选效果。

属性pointerAtLeftHalf 用于普通模式下控制半星展示,当绑定值包含小数位时为true

Icon类名使用计算属性decimalIconClass设置,跟上一小节的activeClass实现一样。

半选显示样式通过计算属性decimalStyle控制,返回包含选中颜色、宽度的样式对象。

  • 只读模式下,按照小数位百分比 valueDecimal 显示宽度。

  • 非只读模式下,小数位不管多大,只显示半颗星 50%

不同模式下样式对比如下:

image.png

鼠标交互事件

在元素添加一些事件和样式处理逻辑,用于支持鼠标滑动、点击事件。

span元素样式根据只读状态设置光标的类型。

mousemove事件监听方法setCurrentValue,用于设置鼠标悬停元素索引 hoverIndex(从1开始)和currentValue,只读模式下无效。

在半选模式下,选择类名el-rate__icon的DOM元素作为目标,获取基于目标节点的内填充边在 X 轴方向上的偏移量 offsetX

如果offsetX小于目标元素的内部宽度的一半,则认为光标在目标元素的左半边,pointerAtLeftHalf 值为 truecurrentValue值为 item-0.5;反之pointerAtLeftHalf 值为 falsecurrentValue值为 item。所以选中效果就是半星->整星整星->半星 的过程。

属性hoverIndex 用于icon图标鼠标悬停放大效果。

mouseleave事件监听方法resetCurrentValue,用于重置pointerAtLeftHalfhoverIndexcurrentValue等属性值,只读模式下无效

clcik事件监听方法selectValue用于触发组件自定义change事件,返回改变后的分值,只读模式下无效。 $emit('input', val) 用来更新组件v-model 值。

辅助文字

类名el-rate__text的span元素用于显示辅助文字,是否显示由属性 showTextshowScore值控制,文字的颜色由属性 textColor控制。

显示内容使用了计算属性 text。 当 showScore=true, 显示当前分数,将当前组件分值使用 scoreTemplate 模板进行内容格式化。 当 showText=true, 显示当前辅助文字,基于当前组件分值调用对应索引(属性 texts)的文字描述。

属性showTextshowScore不能同时为真。

键盘事件

回到根节点,添加如下代码。

属性 rolearia-valuenowaria-valuetextaria-valueminaria-valuemax用于实现 ARIA无障碍网页应用。

属性 tabindex="0" 表示元素是可聚焦的,并且可以通过键盘导航来聚焦到该元素。

添加方法handleKey监听keydown事件,只读模式下无效。

  • 当根节点元素聚焦后,使用方向键增加/减少分值,按下键Up/Right用于增加分值,按下键Left/Down用于减少分值。默认步进为1,当允许半选时,步进为0.5

  • 边界值处理,最小值(0)和最大值(max)。

  • 最后触发组件定义change事件,返回改变后的分值;同时更新v-model值。

组件需要指定一个$emit('input')来改变组件v-model值,否则无法更新用户传入的v-model值。


组件样式

组件样式源码 packages\theme-chalk\src\rate.scss 使用混合指令 be 嵌套生成组件样式。

created,增加逻辑如果value传入非数值,使用$emit('input', 0),更新v-model值为0。


📚参考&关联阅读

"ARIA",MDN "Element/mousemove_event",MDN "tabindex",MDN

最后更新于