likes
comments
collection
share

Vue五星评分组件设计与实现:从基础到进阶

作者站长头像
站长
· 阅读数 17

根据之前的学习,了解到Vue中的组件化的强大,不仅简洁高效,还可以复用。这代表着,当我们先将每个组件做好,然后将这些组件拼在一起,就像是在拼乐高一样,最后组成一个成品。而且这些组件我们还能用在不同的地方,甚至不同的项目也可以使用同一个组件。比如一些美团和淘宝的评分页面中的五星好评:

Vue五星评分组件设计与实现:从基础到进阶 Vue五星评分组件设计与实现:从基础到进阶

那我们是不是也可以做一个专门的五星好评的组件呢,用于以后我们的项目中。试试看吧

star

思路

  • 开头就不用多说,创建一个Vue项目命名为star就好,方便以后我们的查找和使用。将里面我们用不上的东西通通删掉,然后呢创建一个组件名为Rate0吧。
  • Rate组件中就存放展示星星的逻辑就好了,当有数据传入的时候,就显示几颗星星就行
  • 这样的话,我们需要将Rate作为子组件挂载在根组件App上,就可以用了
  • 而App中存放我们的数据信息,利用组件间通信的原则,数据状态归父组件管理 ,通过props 传递给子组件
  • 而我们的子组件不可以直接修改父组件的数据状态,只需要接受参数,做出响应就行。

Rate0组件

代码片段

Vue五星评分组件设计与实现:从基础到进阶

在这里,我们运用vue中提供的defineProps方法和 computed属性:

  • defineProps是Vue 3中用于定义组件接收的props的��方法。它替代了旧版本Vue中的props选项,并提供了类型检查和默认值设置等功能。使用defineProps可以使你的组件更加健壮,因为它确保了传入的props符合预期的类型和格式。例如,在我的Rate组件中,defineProps被用来声明value prop的类型为Number。如果接收到的值不是数值,就会触发一个警告。
  • computed属性是Vue中一种高效的方式,用于基于响应式依赖项计算派生数据。当依赖项改变时,computed属性会自动重新计算其值,而且只有在其相关依赖发生更改时才会重新计算,这可以避免不必要的计算和渲染。例如,这里rate依赖于props.value,每当value更新时,rate也会自动更新。

这里我们采用字符串切割的方法,使用slice()方法来动态生成这个字符串。

  • '★★★★★☆☆☆☆☆' 是一个包含固定数量星星的字符串,前五个是“满星”,后五个是“空星”。

  • slice(5 - props.value, 10 - props.value) 这个表达式根据props.value的大小从原始字符串中截取子串:

    • 如果value是5,则slice(0, 5)会返回所有的“满星”。
    • 如果value是1,则slice(4, 9)会返回一个“满星”后面跟着四个“空星”。

这样的话,我们就不是可以根据父组件传递下来的值,进行响应式更新数据了嘛

App根组件

  • 我们先将star的数量设置为具体的某个值看看效果。

Vue五星评分组件设计与实现:从基础到进阶

运行结果

Vue五星评分组件设计与实现:从基础到进阶

OK的,相关效果已经实现了,并且还测试了一下,如果传入的不是规定的数值,就会触发警告。

Rate1组件

既然已经实现了,那么我们再来想想看,他们商家的星星好像不是黑色,每家的星星颜色都有点不同吧。呦西,再在父组件中加入一个参数theme来设置颜色不就好了,之后想要什么颜色就设什么颜色呗

App根组件

Vue五星评分组件设计与实现:从基础到进阶

Rate1组件

Vue五星评分组件设计与实现:从基础到进阶

运行结果

Vue五星评分组件设计与实现:从基础到进阶

好像还可以吧,通过父组件传过来的参数,去修改css样式,以达到改变颜色的效果。

Rate2组件

可是,好像美团和淘宝上的是通过手点的方式来改变的星星的多少。那我们是不是也可以这样做呢。所以我们需要一个可以通过鼠标悬停和点击来动态调整评分组件。OK那就来升级一下

构造一下思路

  • 首先,我们需要五个空星和五个实星,将他们放在同一个div容器中,之后需要他们一个个显示,所以就不用上面的方法(把他们放在一个字符串里),用v-for循环输出每个星星,并且每个星星上都有对应的key,方便之后的定位。
  • 通过设置该div容器的css样式与实星的css样式为父子元素关系,这样实星就可以相对于div容器来定位,而不会影响其他的元素布局
  • 然后就是考虑鼠标悬在星星上时,应该要触发某个方法,来实时改变某个状态,将实星显示出来,覆盖在空星上
  • 当鼠标不在星星上的时候,也应该要触发某个方法,让状态恢复到之前的状态或者点击之后的状态,这样就解决了鼠标移入移出时,星星的变化效果
  • 那么当我们点击的时候,要触发某个方法去修改星星的数量值,而子组件不可以直接修改父组件的数据状态,需要通过自定义事件传递给父组件,所以要在父组件App中创建一个自定义事件来改变星星的数量值,并且将这个方法传给子组件,然后子组件中设置一个点击事件并且获取到星星的数量值,之后再调用传过来的自定义事件。

App根组件 先在App根组件中,创建好自定义事件,并传给子组件

Vue五星评分组件设计与实现:从基础到进阶

Rate2组件

  • 先按照思路,在<template>中将html代码先写入,将各个事件命名好

        <div :style="fontStyle">
            <div class="rate" @mouseout="mouseOut">
                <span @mouseover="mouseOver(num)" v-for="num in 5" :key="num"></span>
                <span class="hollow" :style="fontwidth">
                    <span @click="onRate(num)" @mouseover="mouseOver(num)" v-for="num in 5" :key="num"></span>
                </span>
            </div>
        </div>
    
  • 然后在<script setup>中将每个事件都实现一下。

    import { ref, defineProps, computed, defineEmits } from 'vue';
    let props = defineProps({
        value: Number,
        theme: { type: String, default: 'orange'}
    })
    let width = ref(props.value)
    let fontwidth = computed(() => `width: ${width.value}em;`);
    let themeObj = {
        orange: '#fa541c',
        blue: '#40a9ff',
        green: '#73d13d',
        black: '#000',
        red: '#f5222d',
        yellow: '#fadb14'
    }
    const fontStyle = computed(() => {
        return `color: ${themeObj[props.theme]}`
    })
    let emits = defineEmits(["update-rate"])
    const onRate = (num) => {
        emits("update-rate", num)
    }
    function mouseOver(i) {
        width.value = i;
    } 
    function mouseOut() {
        width.value = props.value;
    }
    

    通过修改装着实星这个容器的宽度去展示实星的个数。这里要注意从父组件中获取自定义事件的方法defineEmits以及使用方法,要传入俩个参数(一个是自定义事件,一个是接受的参数,这里是需要修改的星星个数)

  • 最后是<style lang="css" scoped>的编译,运用position来定位

        .rate {
            position: relative;
            display: block;
        }
        .rate span{
            display: inline-block;
            width: 1rem;
            height: 22px;
            overflow: hidden;
        }
        .rate > span.hollow {
            position: absolute;
            display:block;
            top:0;
            left:0;
            width:0;
            overflow:hidden;
        }
    

运行结果

Vue五星评分组件设计与实现:从基础到进阶

OK了,这里就将淘宝的五星好评整出来了,以后自己也可以直接用了。

结尾

通过一系列的迭代和优化,我们成功地从零开始构建了一个高度可定制的五星评分组件。从最初的静态展示到动态响应用户交互,再到最终实现鼠标悬停预览与点击评分的功能,我们不仅学习了Vue.js的核心概念,如响应式状态管理、组件通信以及样式定制,还深入了解了如何利用Vue的Composition API来组织和封装组件逻辑。

这一过程展示了Vue.js框架的强大和灵活性,以及组件化开发模式的高效性。无论是对于初学者还是有一定经验的开发者来说,这样的实践都是提升技能和理解Vue架构的绝佳方式。

未来,我们可以轻松地复用这个组件,或者在此基础上进一步扩展,加入更多个性化功能,如半星评分、动画效果等。组件化开发不仅简化了前端开发流程,还提高了代码的重用性和项目的可维护性。

如果你对本文有任何疑问或见解,欢迎留言讨论。期待在前端开发的学习旅程中,与你一起加油!

转载自:https://juejin.cn/post/7389925417786802213
评论
请登录