之前有做过一个高仿饿了么外卖APP
我觉得里面评分组件中的星星效果很值得记录下来以备以后项目需要拿出来借鉴
实现图中的效果有很多方法,我们一般想到的都是用JS条件语句来根据评分的值来控制星星背景图片的偏移,此方法虽然可行,但是有点笨,特别是评分很高时就需要很多重复代码。。特别是响应式、移动端当道的今天,此方法需要加载更多尺寸的图片,不利于SEO。
话不多说,下面开始我们评分星星的star.vue组件的开发
首先:我们要准备好素材,也就是把星星切成单个的星星,分为全星,半星和灰色全星
如下图
我们可根据项目需要来划分星星的尺寸,比如有多个地方需要评分功能,但是星星尺寸大小不一,你就可以切不同尺寸的单个星星。根据星星的尺寸不同可以这样命名:拿全星来说吧,当需要48*48大小的星星时,我们可以这样命名:star48_on@3x.png,当需要36*36大小的星星时我们可以这样命名star36_on@3x.png
接下来我们新建一个star.vue文件
template部分内容如下
其中:class绑定的starType值就是上面所说的根据项目需求来确定的星星尺寸,我们可以通过vue的计算属性来确定星星的尺寸从而返回响应的类名 ,代码如下
computed:{
starType() {
return 'star-' + this.size;
}
}
我们就可以根据starType返回的类名来设定相应尺寸的星星背景图片
从tempalte我们看到,我们是通过vue中的v-for来确定span的个数而不是直接写如下代码固定个数的span
<span class="star-item" :class=""></span>
<span class="star-item"></span>
<span class="star-item"></span>
<span class="star-item"></span>
<span class="star-item"></span>
通过v-for我们可以根据相应情况判定不同星星的个数
itemClasses的值我们也是通过vue中的计算属性和从后台mock的数据返回的评分确定
我们可以在vue的computed钩子中算出itemClasses返回值,代码如下
const LENGTH = 5;//定义星星个数
const CLS_ON = 'on';//定义全星的类名
const CLS_HALF = 'half';//定义半星的类名
const CLS_OFF = 'off';//定义灰色全星的类名
computed:{
itemClasses() {
let result = [];//首先我们定义一个数组用来存放星星的个数
let score = Math.floor(this.score * 2) / 2;/*评分乘以2向下取整再除以2就可以算出是否有半星,比如评分是3.6 套用公式就是Math.floor(3.6*2)/2=3.5 */
let hasDecimal = score % 1 !== 0;//根据变量score返回的值,上面的值是3.5 套用该公式可知hasDecimal !==0
let interger = Math.floor(score);//根绝变量score返回的值向下取整得到整数部分的值,也就是全星的个数
for(let i=0;i<interger;i++){
result.push(CLS_ON);//根据条件遍历interger的值返回响应的全星个数,然后push到result数组中
}
if(hasDecimal) {
result.push(CLS_HALF);//根据hasDecimal返回的值判断是否有半星,有就push到result数组
}
while (result.length < LENGTH) {//判断result数组的长度是否小于星星长度,小于就显示灰色全星
result.push(CLS_OFF);
}
return result;//最后返回result数组
}
}
由上面的代码可知itemClasses返回的是一个存放星星状态的数组,我们就可以通过v-for来遍历这个数组得到相应状态的星星
上面代码中评分为3.5对应的星星显示就如下图:
打开控制台,可以看到解析出来的DOM结构如下
由此可见此法灵活,可复用性强....
(完)