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 遵循单向数据流原则,即数据只能从父组件流向子组件,子组件不能直接修改父组件的数据。这样的设计优点在于能够使数据的流动更加清晰且可预测,有效避免了数据的混乱和不一致性。