评分组件-"星级"服务
前言
评分组件在前端开发中确实是一个既实用又精致的功能模块,它不仅提升了用户体验,还增强了网站或应用的互动性和数据收集能力。这种组件通常以星级评分的形式出现,通过让用户直观地评价商品、服务或内容的质量,为其他用户提供参考,并帮助商家或内容提供者改进产品或服务。
评分组件实现
App.vue :父组件
Rate.vue: 评分子组件
要实现一个优雅的星级评分组件,需要完成以下关键业务:
-
状态管理:
-
初始化评分值,通常为0或默认值。
-
跟踪用户的交互,实时更新评分状态。
-
-
用户交互:
-
鼠标悬停时显示预览评分。
-
点击星星来选择评分,即时更新显示选择的评分值。
-
-
主题可定制性:
- 支持自定义样式,如星星的颜色、大小和形状,以适应不同的设计风格和品牌需求。
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";
// 定义组件接收的 props
const props = defineProps({
score: {
type: Number,
default: 0,
},
theme: {
type: String,
default: "gray",
},
});
// 计算属性,动态生成字体颜色样式
const fontStyle = computed(() => {
return `color:${props.theme}`;
});
// 发送事件的声明
let emits = defineEmits(["update-score"]);
// 组件内部的响应式状态
let width = ref(props.score);
// 计算属性,动态生成选中星星的宽度样式
const fontWidth = computed(() => {
return `width:${width.value}em`;
});
// 点击星星的事件处理函数
const onRate = (num) => {
emits("update-score", num); // 向父组件发送更新评分事件
};
// 鼠标悬停星星的事件处理函数
const mouseOver = (num) => {
width.value = num; // 更新当前选中星星的数量
};
// 鼠标移出评分组件的事件处理函数
const mouseOut = () => {
width.value = props.score; // 恢复原始评分状态
};
</script>
<style lang="css" scoped>
/* 星星的基本样式 */
.star {
letter-spacing: 3px; /* 调整星星之间的间距 */
}
/* 评分组件容器的样式 */
.rate {
position: relative; /* 相对定位,使得内部元素可以用绝对定位 */
display: inline-block; /* 内联块元素,使得评分星星在一行内显示 */
}
/* 选中星星的容器样式 */
.rate > span.hollow {
position: absolute; /* 绝对定位,覆盖在未选中星星上方 */
display: inline-block; /* 内联块元素,与评分星星保持在一行 */
top: 0; /* 顶部对齐 */
left: 0; /* 左侧对齐 */
overflow: hidden; /* 超出部分隐藏,保证只显示部分内容 */
}
</style>
模板部分 (<template>
)
-
样式绑定 (
:style="fontStyle"
) :- 使用了动态样式绑定,将字体颜色设置为组件的 theme 属性所指定的颜色。
-
评分显示 (
<div class="rate">
) :-
使用 v-for 循环渲染5个星星 (☆),用于显示未选中状态的星星。
-
再次使用 v-for 循环渲染5个星星 (★),这些星星被包裹在一个具有动态宽度的容器内 ( class="hollow" ),用于显示选中状态的星星。
-
脚本部分 (<script setup>
)
-
Props 定义 (
defineProps
) :- 定义了两个props:score 和 theme。score 表示当前评分,theme 表示评分组件的主题颜色,默认为灰色。
-
计算属性 (
computed
) :- fontStyle 计算属性根据 props.theme 动态生成字体颜色的样式。
-
响应式变量 (
ref
) :- width 是一个响应式变量,用于跟踪当前的评分宽度(即选中的星星数),初始值为 props.score。
-
事件处理函数:
-
onRate(num):处理点击事件,当用户点击某个星星时触发,通过 emits 向父组件发送 update-score 事件,并传递选中的星星数 num。
-
mouseOver(num):处理鼠标悬停事件,当鼠标悬停在某个星星时触发,动态改变 width 的值,以控制展示选中星星的个数。
-
mouseOut():处理鼠标移出事件,当鼠标移出评分组件时恢复原始的评分状态。
-
样式部分 (<style lang="css" scoped>
)
-
样式作用域:
- 使用了 scoped 属性确保样式只作用于当前组件,防止样式污染。
-
星星样式 (
star
类) :- 设定了星星的字体间距 (letter-spacing: 3px;),用于调整星星之间的间距。
-
评分容器样式 (
rate
类) :- 设定评分容器的布局为 inline-block,使其能够在一行内水平显示。
-
选中星星容器样式 (
hollow
类) :-
使用绝对定位 (position: absolute;),以便在评分容器内显示选中状态的星星覆盖在未选中星星上面。
-
设定 (overflow: hidden);,确保动态显示评分容器内的选中星星的个数,隐藏超出部分。
-
App.vue
<template>
<div><Rate :score="score" theme="yellow" @update-score="update" /></div>
</template>
<script setup>
// 显示打分
import Rate from "./components/Rate.vue";
import { ref } from "vue";
const score = ref(0);
function update(num) {
score.value = num;
}
</script>
<style lang="css" scoped></style>
父组件 :
<Rate :score="score" theme="yellow" @update-score="updateScore" />
:
引入评分组件 Rate.vue
,
通过 :score
属性绑定父组件中的 score
变量,
通过 theme
属性设置评分组件的主题为黄色。
监听子组件的 update-score
事件,并将事件处理函数 updateScore
绑定到该事件上。
效果展示
由于动图一直上传保存不了,十分抱歉,只能以图片展示,小伙伴们可自行参考代码,查看效果。
转载自:https://juejin.cn/post/7390593301509636108