用vue写一个组件库的必备组件:星级评分系统

前言

在许多应用中,用户评分功能是非常常见的需求之一。一个好的评分组件不仅需要实现基本的功能,还应该具备良好的用户体验和高度的可定制性。本文将介绍如何使用Vue构建一个动态、可定制主题的评分组件,来扩充我们的组件库。

文末有我在前端面试多年的经验文章!!!

正文

组件设计

我们的评分组件可以实现的功能:

  • 用户可以通过点击星星来给内容打分。
  • 当鼠标悬停在星星上时,半选中的星星会显示完整状态。
  • 当鼠标离开后,星星状态固定。
  • 用户可以自定义评分的主题颜色。

准备工作

准备两个文件:在src下的App.vue和在srccomponents文件夹下的Rate.vue

开始操作

当前页面:App.vue

开始动手操作,首先,我们从父组件开始,它包含了评分组件以及更新评分逻辑,我们来到App.vue

<template>
  <div>
    <Rate @update-score="update" :score="score" theme="yellow"></Rate>
  </div>
</template>

<script setup>
import Rate from './components/Rate.vue'
import { ref } from 'vue'

// 初始评分为 3 星
let score = ref(3)

function update(num) {
  score.value = num
}
</script>

<style lang="scss" scoped>
/* 样式可以根据需要添加 */
</style>

解析

  • 首先评分前,我们把星星默认设置为三颗(let score = ref(3)),把他声明为响应式数据,用于后面更改星星的个数,:score="score动态绑定星星的个数,当score 的值发生变化时,Vue会自动更新与之绑定的属性,因此,当 score 的值在父组件中发生变化时,子组件也会接收到新的值,并根据新的值更新其显示的评分,这里实现父组件组件向子组件通信,来传递数据。
  • 接着@update-score="update"@update-score是在子组件发布一个事件(下面代码可以看到),我们在父组件里这里订阅,里面传递了子组件给父组件的星星个数,这里实现子组件向父组件通信,来传递数据,我们通过function update(num)这个函数接受子组件传来的数据,并把星星个数更新掉(这时当鼠标点击评完分后鼠标离开星星,只要不再次点击,就默认为这个个数)
  • 最后我们可以通过theme="yellow"把星星的颜色设置成自己想要的颜色,这里的静态字符串 "yellow" 作为值传递给子组件的 theme 属性,前面不用带 v-bind:/:

当前页面:Rate.vue

然后我们来到components文件夹下的Rate.vue,这里是实现功能的核心区域。

<template>
    <div :style="fontStyle">
        <div class="rate" @mouseout="mouseOut">
            <span class="star"  @mouseover="mouseOver(num)" v-for="num in 5":key="num">☆</span>
            <span class="hollow" :style="fontWidth">
                <span class="star" @click="onRate(num)" @mouseover="mouseOver(num)" v-for="num in 5":key="num">★</span>
            </span>
        </div>
    </div>
</template>

<script setup>
import {defineProps,computed,defineEmits,ref } from 'vue'
let props = defineProps({
    score:{
        typeof:Number,
        default:0,
    },
    theme:{
        typeof:String,
        default:'blue',
    }
})

//主题可定制性
const themeObj={
    'black': '#000',
    'yellow': '#fadb14',
    'blue': '#40a9ff',
    'green':'#73d13d'
}
const fontStyle=computed(()=>{
    return `color:${themeObj[props.theme]};`
})
//私有状态 mouseover mouseout 改变状态
let width=ref(props.score)


let emits=defineEmits(['update-score'])
const onRate=(num)=>{
    emits('update-score',num)
}
const fontWidth=computed(()=> `width:${width.value}em;`)

const mouseOver=(num)=>{
    width.value=num
}

const mouseOut=()=>{
    width.value=props.score
}
</script>

<style lang="css" scoped>
.star{
    letter-spacing: 3px;
    cursor: pointer;
}

.rate{
    position: relative;
    display: inline-block;
}
.rate>span.hollow{
    position: absolute;
    display: inline-block;
    top:0;
    left: 0;
    overflow: hidden;   
}
</style>

解析

1.首先我们通过let props = defineProps()接收到从父组件传来的数据:scoretheme,如果没有传就默认为零颗星星和默认星星为蓝色,:style="fontStyle"通过父组件传来的颜色设置星星的颜色。
2.接着我们通过v-for="num in 5"把五颗☆和★放在一行通过top:0和left: 0;把两组星星重合,这里一直都是五颗☆和★,letter-spacing: 3px;,设置了每个星星的间隙,:style="fontWidth"用于把个数转换为宽度,已经设置好了,星星能够完整的覆盖,如果通过循环个数来实现的话,当鼠标来回移动,就不算是mouseover了就实现不了上面的动画效果了,所以我们才把个数变为宽度,并且通过overflow: hidden;把多的星星隐藏掉来实现效果。
3.@mouseout="mouseOut"@mouseover="mouseOver(num),"@click="onRate(num)",都是修改星星的个数来修改宽度的,let emits=defineEmits(['update-score'])发布一个事件,当用户点击后,这个事件携带者数据传给父组件,父组件订阅后就可以获得这个数据来使用了。

总结

通过以上代码,这样我们就可以创建一个功能完备且外观美观的评分组件。此外,该组件支持多种主题颜色,使得它能够适应不同的应用场景。希望这个示例能帮助你理解 Vue中组件的实现细节,并激发你创建更多有趣的应用。感谢你的阅读!

接下来给大家推荐一篇我在前端面试多年的经验文章,希望大家看完以后都可以领取到心仪的offer哦!

文章:《聊聊前端面试那些事儿》

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值