element-ui Rate组件源码分析整理笔记(十三)
Rate组件源码比较简单,有添加部分注释
main.vue
<template>
<!--valuenow当前的评分 valuetext当前显示的文本-->
<div
class="el-rate"
@keydown="handleKey"
role="slider"
:aria-valuenow="currentValue"
:aria-valuetext="text"
aria-valuemin="0"
:aria-valuemax="max"
tabindex="0">
<!--包裹每个星的标签-->
<span
v-for="(item, key) in max"
class="el-rate__item"
@mousemove="setCurrentValue(item, $event)"
@mouseleave="resetCurrentValue"
@click="selectValue(item)"
:style="{ cursor: rateDisabled ? 'auto' : 'pointer' }"
:key="key">
<!--显示评星的标签-->
<i :class="[classes[item - 1], { 'hover': hoverIndex === item }]"
class="el-rate__icon"
:style="getIconStyle(item)">
<!--这里主要是当评分出现小数,显示左边高亮的半星-->
<i v-if="showDecimalIcon(item)"
:class="decimalIconClass"
:style="decimalStyle"
class="el-rate__decimal">
</i>
</i>
</span>
<!--showText是否显示辅助文字,若为真,则会从 texts 数组中选取当前分数对应的文字内容;showScore是否显示当前分数,show-score 和 show-text 不能同时为真-->
<span v-if="showText || showScore" class="el-rate__text" :style="{ color: textColor }">{{ text }}</span>
</div>
</template>
<script>
import { hasClass } from 'element-ui/src/utils/dom';
import Migrating from 'element-ui/src/mixins/migrating';
export default {
name: 'ElRate',
mixins: [Migrating],
//provider/inject:简单的来说就是在父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量。
inject: {
elForm: {
default: ''
}
},
data() {
return {
pointerAtLeftHalf: true,
currentValue: this.value,
hoverIndex: -1
};
},
props: {
value: {
type: Number,
default: 0
},
lowThreshold: { //低分和中等分数的界限值,值本身被划分在低分中
type: Number,
default: 2
},
highThreshold: { //高分和中等分数的界限值,值本身被划分在高分中
type: Number,
default: 4
},
max: { //最大分值
type: Number,
default: 5
},
colors: { //icon 的颜色数组,共有 3 个元素,为 3 个分段所对应的颜色
type: Array,
default() {
return ['#F7BA2A', '#F7BA2A', '#F7BA2A'];
}
},
voidColor: { //未选中 icon 的颜色
type: String,
default: '#C6D1DE'
},
disabledVoidColor: { //只读时未选中 icon 的颜色
type: String,
default: '#EFF2F7'
},
iconClasses: { //icon 的类名数组,共有 3 个元素,为 3 个分段所对应的类名
type: Array,
default() {
return ['el-icon-star-on', 'el-icon-star-on', 'el-icon-star-on'];
}
},
voidIconClass: { //未选中 icon 的类名
type: String,
default: 'el-icon-star-off'
},
disabledVoidIconClass: { //只读时未选中 icon 的类名
type: String,
default: 'el-icon-star-on'
},
disabled: { //是否为只读
type: Boolean,
default: false
},
allowHalf: { //是否允许半选
type: Boolean,
default: false
},
showText: { //是否显示辅助文字,若为真,则会从 texts 数组中选取当前分数对应的文字内容
type: Boolean,
default: false
},
showScore: { //是否显示当前分数,show-score 和 show-text 不能同时为真
type: Boolean,
default: false
},
textColor: { //辅助文字的颜色
type: String,
default: '#1f2d3d'
},
texts: { //辅助文字数组
type: Array,
default() {
return ['极差', '失望', '一般', '满意', '惊喜'];
}
},
scoreTemplate: { //分数显示模板
type: String,
default: '{value}'
}
},
computed: {
text() {
let result = '';
//如果显示当前分数
if (this.showScore) {
//如果当前是只读状态,就显示v-model绑定的值,否则根据用户的评分显示值
result = this.scoreTemplate.replace(/\{\s*value\s*\}/, this.rateDisabled
? this.value
: this.currentValue);
} else if (this.showText) { //如果显示辅助文字,则根据用户设置评分currentValue来显示texts数组中的文字
result = this.texts[Math.ceil(this.currentValue) - 1];
}
return result;
},
//高亮半星时添加的样式,颜色以及宽度
decimalStyle() {
let width = '';
if (this.rateDisabled) {
//这里判断value的值是否含有小数,有小数的则这里宽度为50%,为整数的话为0%
width = `${ this.valueDecimal < 50 ? 0 : 50 }%`;
}
if (this.allowHalf) {
width = '50%';
}
return {
color: this.activeColor,
width
};
},
valueDecimal() {
return this.value * 100 - Math.floor(this.value) * 100;
},
decimalIconClass() {
return this.getValueFromMap(this.value, this.classMap);
},
voidClass() {
return this.rateDisabled ? this.classMap.disabledVoidClass : this.classMap.voidClass;
},
//根据currentValue的分所在的等级,返回对应的类名
activeClass() {
return this.getValueFromMap(this.currentValue, this.classMap);
},
colorMap() {
return {
lowColor: this.colors[0],
mediumColor: this.colors[1],
highColor: this.colors[2],
voidColor: this.voidColor,
disabledVoidColor: this.disabledVoidColor
};
},
//根据currentValue的分所在的等级,返回对应的颜色
activeColor() {
return this.getValueFromMap(this.currentValue, this.colorMap);
},
//这里主要是判断该星是选中还是未选中,分别加入选中和未选中icon类名
classes() {
let result = [];
let i = 0;
let threshold = this.currentValue;
if (this.allowHalf && this.currentValue !== Math.floor(this.currentValue)) {
threshold--;
}
for (; i < threshold; i++) {
result.push(this.activeClass);
}
for (; i < this.max; i++) {
result.push(this.voidClass);
}
return result;
},
classMap() {
return {
lowClass: this.iconClasses[0],
mediumClass: this.iconClasses[1],
highClass: this.iconClasses[2],
voidClass: this.voidIconClass,
disabledVoidClass: this.disabledVoidIconClass
};
},
rateDisabled() {
//是否为只读,或者父组件el-form中disabled的属性值,disabled是否禁用该表单内的所有组件。若设置为 true,则表单内组件上的 disabled 属性不再生效
return this.disabled || (this.elForm || {}).disabled;
}
},
watch: {
value(val) {
this.currentValue = val;
this.pointerAtLeftHalf = this.value !== Math.floor(this.value);
}
},
methods: {
getMigratingConfig() {
return {
props: {
'text-template': 'text-template is renamed to score-template.'
}
};
},
//判断当前value在属于低分、中等分、高分中的哪个,根据不同等级返回不同的类名或者颜色
getValueFromMap(value, map) {
let result = '';
if (value <= this.lowThreshold) {
result = map.lowColor || map.lowClass;
} else if (value >= this.highThreshold) {
result = map.highColor || map.highClass;
} else {
result = map.mediumColor || map.mediumClass;
}
return result;
},
showDecimalIcon(item) {
//如果当前value包含小数,并且item - 1 < this.value <item, showWhenDisabled为true
let showWhenDisabled = this.rateDisabled && this.valueDecimal > 0 && item - 1 < this.value && item > this.value;
//这里主要也是判断是否当前星是否应显示半星
let showWhenAllowHalf = this.allowHalf &&
this.pointerAtLeftHalf &&
item - 0.5 <= this.currentValue &&
item > this.currentValue;
return showWhenDisabled || showWhenAllowHalf;
},
//返回当前星图标的颜色
getIconStyle(item) {
//voidColor的值是根据是否只读来判断返回disabled-void-color或者void-color
const voidColor = this.rateDisabled ? this.colorMap.disabledVoidColor : this.colorMap.voidColor;
return {
//判断当前星是显示高亮的颜色还是未选中时的颜色
color: item <= this.currentValue ? this.activeColor : voidColor
};
},
//点击时设置值
selectValue(value) {
if (this.rateDisabled) {
return;
}
//当可以显示半星时,这块传递的值为currentValue(鼠标移上去时会计算是否超过一半)
if (this.allowHalf && this.pointerAtLeftHalf) {
this.$emit('input', this.currentValue);
this.$emit('change', this.currentValue);
} else { //当不显示半星直接返回value
this.$emit('input', value);
this.$emit('change', value);
}
},
//当按键按下时所调用的方法
handleKey(e) {
//如果组件被禁用则按键事件无效
if (this.rateDisabled) {
return;
}
let currentValue = this.currentValue;
const keyCode = e.keyCode;
//当按上下左右键的时候,允许半选则在currentValue加或减0.5,不允许则加或减1
if (keyCode === 38 || keyCode === 39) { // up / right
if (this.allowHalf) {
currentValue += 0.5;
} else {
currentValue += 1;
}
e.stopPropagation();
e.preventDefault();
} else if (keyCode === 37 || keyCode === 40) { // left /down
if (this.allowHalf) {
currentValue -= 0.5;
} else {
currentValue -= 1;
}
e.stopPropagation();
e.preventDefault();
}
currentValue = currentValue < 0 ? 0 : currentValue;
currentValue = currentValue > this.max ? this.max : currentValue;
//将currentValue通过input传递给子组件绑定的v-model值,触发change事件,子组件可以change在获取改变后的值
this.$emit('input', currentValue);
this.$emit('change', currentValue);
},
//鼠标移动时改变评星的值
setCurrentValue(value, event) {
if (this.rateDisabled) {
return;
}
/* istanbul ignore if */
if (this.allowHalf) {
let target = event.target;
//鼠标移动到包裹星星图标的span标签时,获取到显示星的icon标签
if (hasClass(target, 'el-rate__item')) {
target = target.querySelector('.el-rate__icon');
}
if (hasClass(target, 'el-rate__decimal')) {
target = target.parentNode;
}
//根据鼠标移到一颗星的左边一半以内的位置,则减去当前值的0.5,否则就是等于当前值
this.pointerAtLeftHalf = event.offsetX * 2 <= target.clientWidth;
this.currentValue = this.pointerAtLeftHalf ? value - 0.5 : value;
} else {
//不允许半选时,鼠标移到那颗星就等于当前的值
this.currentValue = value;
}
//记录鼠标移动的位置
this.hoverIndex = value;
},
//鼠标移出时设置当前的值
resetCurrentValue() {
if (this.rateDisabled) {
return;
}
if (this.allowHalf) {
//如果当前的value是小数,pointerAtLeftHalf为true,如果是整数则为false,这里主要是为了点击时用来判断传哪个值
this.pointerAtLeftHalf = this.value !== Math.floor(this.value);
}
//鼠标移上去时currentValue会改变,移走时currentValue等于之前的value
this.currentValue = this.value;
this.hoverIndex = -1;
}
},
created() {
if (!this.value) {
this.$emit('input', 0);
}
}
};
</script>
element-ui Rate组件源码分析整理笔记(十三)的更多相关文章
- element-ui 组件源码分析整理笔记目录
element-ui button组件 radio组件源码分析整理笔记(一) element-ui switch组件源码分析整理笔记(二) element-ui inputNumber.Card .B ...
- element-ui button组件 radio组件源码分析整理笔记(一)
Button组件 button.vue <template> <button class="el-button" @click="handleClick ...
- element-ui input组件源码分析整理笔记(六)
input 输入框组件 源码: <template> <div :class="[ type === 'textarea' ? 'el-textarea' : 'el-in ...
- element-ui MessageBox组件源码分析整理笔记(十二)
MessageBox组件源码,有添加部分注释 main.vue <template> <transition name="msgbox-fade"> < ...
- element-ui Message组件源码分析整理笔记(八)
Message组件源码: main.js import Vue from 'vue'; import Main from './main.vue'; import { PopupManager } f ...
- element-ui Steps步骤条组件源码分析整理笔记(九)
Steps步骤条组件源码: steps.vue <template> <!--设置 simple 可应用简洁风格,该条件下 align-center / description / ...
- Element UI table组件源码分析
本文章从如下图所示的最基本的table入手,分析table组件源代码.本人已经对table组件原来的源码进行削减,源码点击这里下载.本文只对重要的代码片段进行讲解,推荐下载代码把项目运行起来,跟着文章 ...
- element-ui inputNumber、Card 、Breadcrumb组件源码分析整理笔记(三)
inputNumber组件 <template> <!--@dragstart.prevent禁止input中数字的拖动--> <div @dragstart.preve ...
- element-ui Upload 上传组件源码分析整理笔记(十四)
简单写了部分注释,upload-dragger.vue(拖拽上传时显示此组件).upload-list.vue(已上传文件列表)源码暂未添加多少注释,等有空再补充,先记下来... index.vue ...
随机推荐
- PyCharm常用快捷键(pycharm使用教程)
pycharm常用快捷键与设置 pycharm高频率使用的快捷键 Ctrl+Shift+F10 运行当前的页面 Ctrl + / 注释(取消注释)选择的行 Ctrl+Shift+F 高级查找 Shif ...
- Android开源日志框架xlog
版权声明:本文为xing_star原创文章,转载请注明出处! 本文同步自http://javaexception.com/archives/144 xlog的优点 在开发过程中,避免不了要使用日志组件 ...
- 【LeetCode】746. 使用最小花费爬楼梯
使用最小花费爬楼梯 数组的每个索引做为一个阶梯,第 i个阶梯对应着一个非负数的体力花费值 cost[i](索引从0开始). 每当你爬上一个阶梯你都要花费对应的体力花费值,然后你可以选择继续爬一个阶梯或 ...
- (二)Amazon Lightsail 部署LAMP应用程序之部署单片LAMP应用程序
部署单片LAMP应用程序 简介:通过复制应用程序代码并提供链接PHP前端和本地MySQL数据库的参数,将LAMP对战应用程序部署到先前启动的Lightsail实例中.完成后,Apache/PHP前端和 ...
- pycharm安装pymysql包
1.为什么? 每个程序连接数据库,python开发2.*版本可以直接使用MySQL,python3.*版本需要下载使用PyMySQL包才能连接数据库... 2. 怎么做? 2.1. 更改源:pycha ...
- day71_10_16多表断关联
---恢复内容开始--- 本次环境: 配置settings INSTALLED_APPS = [ # ... 'rest_framework', ] DATABASES = { 'default': ...
- Appium 定位
使用过 Appium 的都知道,元素的定位方式有很多种,具体使用哪一种,主要看业务的需要和自己的使用爱好.下面总结一下,Appium 到底有哪些定位方式,定位的元素以下面截图指定的元素为例子: 这 ...
- Jenkins配置:添加用户和管理权限
Jenkins配置:添加用户和管理权限 参考文章:http://www.cnblogs.com/zz0412/p/jenkins_jj_14.html 今天给大家说说使用Jenkins专有用户数据库的 ...
- 《从HBase offheap到Netty的内存管理》
JVM中的堆外内存(off-heap memory)与堆内内存(on-heap memory) 1. 堆内内存(on-heap memory) 1.1 什么是堆内内存 Java 虚拟机在执行Jav ...
- json数据转换成结构体
package main import ( "encoding/json" "fmt" ) type IT1 struct { Company string ` ...