vue实现评分

307 阅读5分钟

vue实现评分

在当今的数字化世界中,用户反馈和评价对于提升产品和服务的质量至关重要。评分系统作为一种直观、简洁的用户反馈方式,广泛应用于各种应用场景,如电商平台的商品评价、在线教育的课程评分、社交媒体的内容点赞等。 在 Vue 框架中实现评分功能,不仅能够为用户提供便捷的交互体验,还能帮助开发者更高效地管理和处理用户的评价数据。通过巧妙地运用 Vue 的响应式特性和组件化架构,我们可以打造出一个灵活、可定制且易于维护的评分系统。 在接下来的内容中,我们将深入探讨如何使用 Vue 来构建一个功能完善、外观精美的评分组件,满足不同业务需求的同时,为用户带来流畅、愉悦的操作感受。

话不多说,上代码

APP.vue下的内容

<template>
  <div>
    <Rate1 :value="score" theme="yellow" @update-rate="update" />
    //其中使用了自定义组件 `Rate1` ,并通过 `:value="score"` 为其传递了动态
    //值 `score` ,设置了主题为 `yellow` ,还为 `update-rate` 事件绑定
    //了 `update` 函数。
  </div>
</template>
<script setup>
import Rate1 from './components/Rate1.vue'
//从 `'./components/Rate1.vue'` 导入了自定义组件 `Rate1` 。
import { ref } from 'vue'
let score = ref(0)
//使用 `ref` 创建了一个响应式变量 `score` ,初始值为 `0` 。

function update(num) {
  score.value = num
}
//定义了 `update` 函数,用于接收参数 `num` 并更新 `score` 的值。
</script>

<style lang="css" scoped></style>

Rate1.vue里面的内容

<!-- 为外部的 div 元素应用动态计算的 fontStyle 样式 -->
<div :style="fontStyle">
    <!-- 创建带有 "rate" 类名的 div,并为鼠标移出事件绑定 mouseOut 函数 -->
    <div class="rate" @mouseout="mouseOut">
        <!-- 通过 v-for 循环生成 5 个空星星(☆),为每个星星的鼠标悬停事件绑定 mouseOver 函数,并设置唯一的 key -->
        <span @mouseover="mouseOver(num)" v-for="num in 5" :key="num"></span>
        <!-- 创建带有 "hellow" 类名的 span,并应用动态计算的 fontwidth 样式 -->
        <span class="hellow" :style="fontwidth">
            <!-- 通过 v-for 循环生成 5 个实星星(★),为每个星星的点击事件绑定 onRate 函数和鼠标悬停事件绑定 mouseOver 函数,并设置唯一的 key -->
            <span @click="onRate(num)" @mouseover="mouseOver(num)" v-for="num in 5" :key="num"></span>
        </span>
    </div>
    <!-- <button type="button" @click="onRate(2)">点击</button> -->
</div>

<script setup>
    <!-- 从 Vue 导入所需的函数和模块 -->
    import { defineProps, computed, defineEmits, ref } from 'vue';
    <!-- 定义组件接收的属性 "value"(数字类型)和 "theme"(字符串类型,默认值为 'orange') -->
    let props = defineProps({
        value: Number,
        theme: { type: String, default: 'orange' }
    })
    <!-- 使用 ref 创建响应式变量 width,并初始化为 props.value -->
    let width = ref(props.value);
    <!-- 创建计算属性 fontwidth,根据 width 的值生成宽度样式字符串 -->
    let fontwidth = computed(() => `width:${width.value}em`);
    <!-- 创建计算属性 rate,生成与当前 props.value 相关的星星字符串 -->
    let rate = computed(() => "★★★★★☆☆☆☆☆".slice(5 - props.value, 10 - props.value));
    <!-- 定义不同主题对应的颜色值对象 -->
    let themeObj = {
        orange: '#fa54c',
        blue: '#40a9ff',
        green: '#73d13d',
        black: '#000',
        red: '#f5222d',
        yellow: '#fadb14'
    }
    <!-- 创建计算属性 fontStyle,根据 props.theme 获取对应的颜色值设置字体颜色样式 -->
    const fontStyle = computed(() => {
        return `color:${themeObj[props.theme]}`
    })
    <!-- 定义组件可以触发的自定义事件 "update-rate" -->
    let emits = defineEmits(['update-rate']);
    <!-- 定义 onRate 函数,触发 "update-rate" 事件并传递参数 num -->
    const onRate = (num) => {
        Emits('update-rate', num)
    }
    <!-- 定义 mouseOver 函数,更新 width.value 的值,并打印到控制台 -->
    function mouseOver(i) {
        width.value = i;
        console.log(width.value);
    }
    <!-- 定义 mouseOut 函数,将 width.value 恢复为 props.value -->
    function mouseOut() {
        width.value = props.value
    }
</script>

<style lang="css" scoped>
    <!-- 为 "rate" 类设置样式,相对定位,以块级元素显示 -->
   .rate {
        position: relative;
        display: block;
    }
    <!-- 为 "rate" 类中的 span 元素设置样式,包括字符间距、显示方式、宽度、高度和处理内容溢出 -->
   .rate span {
        letter-spacing: 3px;
        display: inline-block;
        width: 1rem;
        height: 22px;
        overflow: hidden;
    }
    <!-- 为 "rate" 类中的直接子元素 "span.hellow" 设置样式,绝对定位,位置在顶部和左侧的 0 位置,初始宽度为 0,处理内容溢出 -->
   .rate>span.hellow {
        position: absolute;
        display: inline-block;
        top: 0%;
        left: 0;
        width: 0;
        overflow: hidden;
    }
</style>

这段 Vue 3 代码是一个具有评分功能的组件:

  • 在模板部分(<template>):

    • 有一个外部的 <div> ,其样式通过 fontStyle 计算属性动态设置。
    • 内部的 <div class="rate"> 包含了未选中的星星()和选中的星星()。当鼠标悬停在星星上时会触发 mouseOver 函数,鼠标移出时触发 mouseOut 函数,点击星星时触发 onRate 函数并触发自定义事件 update-rate 。
  • 在脚本部分(<script setup>):

    • 通过 defineProps 定义了组件接收的属性 value (数字类型)和 theme (字符串类型,默认值为 'orange' )。
    • 使用 ref 创建了 width 来跟踪当前选中的星星数量。
    • fontwidth 计算属性根据 width 的值设置宽度样式。
    • rate 计算属性生成当前的星星显示字符串。
    • themeObj 定义了不同主题对应的颜色值。
    • fontStyle 计算属性根据主题设置字体颜色。
    • 通过 defineEmits 定义了可以触发的自定义事件 update-rate 。
    • onRate 函数用于触发自定义事件并传递选中的星星数量。
    • mouseOver 函数在鼠标悬停时更新选中的星星数量。
    • mouseOut 函数在鼠标移出时恢复初始选中的星星数量。
  • 在样式部分(<style>):为 rate 及其内部的 span 元素设置了一些基本的样式,如位置、显示方式、宽度、高度等。

主要原理如下:

把空星星和实星星分别放置在 <span> 元素中,借助 v-for 循环生成 5 个。利用样式实现绝对定位,让空星星处于下方,实星星位于上方。设定 @mouseover="mouseOver(num)" 鼠标悬停事件,当鼠标悬停在星星上时,会触发 mouseOver 函数。这个函数用于控制显示的长度,超出该长度的部分通过 CSS 样式予以隐藏,由此实现当鼠标悬浮在某个空星星上时,就显示对应数量的星星。当鼠标移出时,触发 @mouseout 事件,进而执行 mouseOut 函数,实现鼠标移出时恢复初始选中的星星数量。当进行点击操作时,触发 onRate 函数,进而触发根组件的 @update-rate 事件,致使根组件的 update 函数被触发。随后,update 函数会将悬停的星星数量回传给子组件,由子组件进行控制。

需要注意的是,在 Vue 中,子组件通常不应直接修改父组件传递的 props 。这是因为 Vue 遵循单向数据流原则,即数据只能从父组件流向子组件,子组件不能直接修改父组件的数据。这样的设计优点在于能够使数据的流动更加清晰且可预测,有效避免了数据的混乱和不一致性。