一
<template>
<div>
<div class="star mb-10" :class="starType">
<span
class="star-item"
v-for = "(itemClass,i) in itemClassess"
:class="itemClass"
:key="i"
></span>
</div>
</div>
</template>
<script>
const LENGTH = 10;//星星个数
const CLS_ON = "on";//满星状态
const CLS_HALF = "half";//半星状态
const CLS_OFF = "off";//无星状态
export default {
props: {
size: {
type : Number//参数:尺寸
},
score: {
type : Number//参数:评分
}
},
computed: {
starType(){//设置星星尺寸
return "star-" + this.size;
},
itemClassess(){
let result = [];//记录状态的数组
let score = Math.floor(this.score * 2) / 2;
let hasDecimal = score % 1 !==0;
let integer = Math.floor(score);//向下取整
//全星
for(let i = 0; i < integer; i++){
result.push(CLS_ON);
}
//半星
if(hasDecimal){
result.push(CLS_HALF);
}
//无星
if(result.length < LENGTH){
result.push(CLS_OFF);
}
return result;
}
}
}
</script>
<style>
.star {
display: flex;
width: 100%;
}
.star-48 .star-item {
width: 20px;
height: 20px;
margin-right: 22px;
background-repeat: no-repeat;
background-size: 20px 20px;
}
.star-48 .star-item:last-child {
margin-right: 0px;
}
.star-48 .star-item.on {
background-image: url("https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1264157627,2023353298&fm=26&gp=0.jpg");
}
.star-48 .star-item.half {
background-image: url("https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3837197790,4152490133&fm=15&gp=0.jpg");
}
.star-48 .star-item.off {
background-image: url("https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3377642465,2658946556&fm=26&gp=0.jpg");
}
.star-36 .star-item {
width: 15px;
height: 15px;
margin-right: 6px;
background-repeat: no-repeat;
background-size: 15px 15px;
}
.star-36 .star-item:last-child {
margin-right: 0px;
}
.star-36 .star-item:last-child {
margin-right: 0px;
}
.star-36 .star-item.on {
background-image: url("https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1264157627,2023353298&fm=26&gp=0.jpg");
}
.star-36 .star-item.half {
background-image: url("https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3837197790,4152490133&fm=15&gp=0.jpg");
}
.star-36 .star-item.off {
background-image: url("https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3377642465,2658946556&fm=26&gp=0.jpg");
}
</style>
在使用的组件中调用
<Reta :size="48" :score="8.5"></Reta>
size :大小
score :几颗星
这是一种方法 是直接渲染后台返回的数据的
那么再写一种使用点击的方式,逻辑自定义
二
<template>
<div class="star">
<!-- // 用于父子组件双向绑定 -->
<input type="hidden" v-model="value">
<!-- // 不可点击的星星 -->
<div v-if="readonly">
<!-- // 满星 -->
<img v-for="i in parseInt(value)" :key="i" :src="full">
<!-- // 半星 -->
<img v-if="value.toString().indexOf('.') > 0" :src="half">
<!-- // 灰星 -->
<img v-for="i in parseInt(number - value)" :key="i * number+1" :src="empty">
</div>
<!-- // 可点击的星星 -->
<div v-if="!readonly">
<!-- // 满星 -->
<img v-for="i in num" :key="i" :src="full" @click="num = i">
<!-- // 灰星 -->
<img v-for="i in parseInt(number - num)" :key="i * number" :src="empty" @click="num += i">
</div>
</div>
</template>
<script>
export default {
props: {
// 分值
value: {
type: Number,
default: 0
},
// 接收过来的数量
number: {
type: Number,
default: 0
},
// 只读,表示可以点击还是不可点击
readonly: {
type: Boolean,
default: false
}
},
data () {
return {
num: 0,
full:'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1264157627,2023353298&fm=26&gp=0.jpg', // 满星
empty:'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3377642465,2658946556&fm=26&gp=0.jpg', // 没星
half:'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=3837197790,4152490133&fm=15&gp=0.jpg' // 半星
}
},
watch: {
num () {
// 可点击状态下,双向绑定的分值改变
this.$emit('input', this.num)
}
}
}
</script>
<style scoped>
.star img {
width: 24px;
height: 24px;
margin: 0 2px;
}
</style>
在使用的组件中直接调用
<template>
<div>
<span>评分</span>
可点击
<Reta v-model="value" :number="10" @input="inp"/>
不可点击
// <Reta v-model="value" :number="10" readonly />
// 这两个一个可点击一个不可点击的最好别同时使用,不然影响操作,
因为一个可以一个不可以 点击可以的那个参数跟着变化,那个不可点击的也会随着变化 这里只是一个参考作用
</div>
</template>
<script>
import Reta from "@/components/reta"
import Bus from "../utils/Bus"
export default {
components:{Toast},
data(){
return {
value:4.5
}
},
methods:{
// 点击过后多少星,返回过来,这里可以请求后台接口
inp(num)
{
console.log(num)
console.log("点击了"+num+'颗星星')
}
}
}
</script>
整体思路还是比较简单的,我封装的第1种评分使用场景是请求后台接口数据,返回的评分我们直接渲染就可以了
第2种应用场景呢就是比如你叫了个外卖,送餐人员给你送到,你给送餐人员评分,然后获取到评分的数,请求后台接口,
把评分数传给后台