星级评分是用户反馈系统中常见的组件,用户通过点亮星标来对产品、文章或服务进行直观的 1 到 5 星评价。jQuery 结合 Font Awesome 图标库可以快速实现这一功能。下面分别介绍两种交互模式:点击评分和悬停评分。
为什么用两个不同的 jQuery 事件来区分“点击”和“悬停”?
click 和 hover 在用户体验上有本质区别。click 是用户明确做出选择,适合需要记录结果的评分场景——用户点击后评分结果被锁定,提交表单时可以取到具体分值。hover 则是临时预览,鼠标划过时亮起星标,移开后恢复原状,适合仅展示交互反馈而不需要记录最终值的场合。两者服务于不同阶段的需求,实际项目中经常组合使用:hover 负责预览,click 负责确认。
实现思路
无论是点击还是悬停,核心逻辑都遵循同一条规则:将当前星标及其之前的所有星标都点亮,之后的星标保持暗色。以 5 颗星为例,点击第 3 颗时,第 1、2、3 颗都变亮,第 4、5 颗不变。代码通过组合 ID 选择器 $("#st1, #st2, #st3") 来实现这个效果。
示例一:点击式星级评分
用户点击某颗星后,该星及之前的星全部高亮为金色,后续星保持灰色。这种方式明确记录了用户的评分选择。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>点击星级评分 · 编程学习</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
body {
background-color: #f5f5f5;
margin: 0;
font-family: sans-serif;
}
.rating-container {
text-align: center;
margin: 60px auto;
max-width: 500px;
}
.fa-star {
font-size: 48px;
margin: 0 6px;
color: #ccc;
cursor: pointer;
transition: color 0.15s ease;
}
.rating-label {
font-size: 20px;
color: #333;
margin-bottom: 20px;
}
.score-text {
margin-top: 18px;
font-size: 18px;
color: #555;
}
</style>
</head>
<body>
<div class="rating-container">
<h2>点击星级评分示例</h2>
<p class="rating-label">请为我们的课程内容打分:</p>
<div class="stars">
<i class="fa fa-star" aria-hidden="true" id="st1"></i>
<i class="fa fa-star" aria-hidden="true" id="st2"></i>
<i class="fa fa-star" aria-hidden="true" id="st3"></i>
<i class="fa fa-star" aria-hidden="true" id="st4"></i>
<i class="fa fa-star" aria-hidden="true" id="st5"></i>
</div>
<p class="score-text">当前评分:<span id="rating-value">未评分</span></p>
</div>
<script>
$(document).ready(function () {
// 第 1 颗星
$("#st1").click(function () {
$(".fa-star").css("color", "#ccc"); // 全部重置为灰色
$("#st1").css("color", "#f5a623"); // 点亮第 1 颗
$("#rating-value").text("1 星");
});
// 第 2 颗星
$("#st2").click(function () {
$(".fa-star").css("color", "#ccc");
$("#st1, #st2").css("color", "#f5a623"); // 点亮前 2 颗
$("#rating-value").text("2 星");
});
// 第 3 颗星
$("#st3").click(function () {
$(".fa-star").css("color", "#ccc");
$("#st1, #st2, #st3").css("color", "#f5a623");
$("#rating-value").text("3 星");
});
// 第 4 颗星
$("#st4").click(function () {
$(".fa-star").css("color", "#ccc");
$("#st1, #st2, #st3, #st4").css("color", "#f5a623");
$("#rating-value").text("4 星");
});
// 第 5 颗星
$("#st5").click(function () {
$(".fa-star").css("color", "#ccc");
$("#st1, #st2, #st3, #st4, #st5").css("color", "#f5a623");
$("#rating-value").text("5 星");
});
});
</script>
</body>
</html>
点击任一颗星后,页面下方会同步显示当前的具体分值。所有星先统一重置为灰色,再点亮目标星及之前的全部星星,确保状态干净不残留。
示例二:悬停式星级评分
悬停模式用 hover 事件替代 click,鼠标划过时星标自动亮起,移开后可在回调中决定是否恢复为默认状态。这种交互常用于引导用户查看评分档位,而不强制留下记录。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>悬停星级评分 · 编程学习</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
body {
background-color: #f5f5f5;
margin: 0;
font-family: sans-serif;
}
.rating-container {
text-align: center;
margin: 60px auto;
max-width: 500px;
}
.fa-star {
font-size: 48px;
margin: 0 6px;
color: #ccc;
cursor: pointer;
transition: color 0.15s ease;
}
.rating-label {
font-size: 20px;
color: #333;
margin-bottom: 20px;
}
.hint-text {
margin-top: 18px;
font-size: 16px;
color: #888;
}
</style>
</head>
<body>
<div class="rating-container">
<h2>悬停星级评分示例</h2>
<p class="rating-label">鼠标划过星标预览评分:</p>
<div class="stars">
<i class="fa fa-star" aria-hidden="true" id="hs1"></i>
<i class="fa fa-star" aria-hidden="true" id="hs2"></i>
<i class="fa fa-star" aria-hidden="true" id="hs3"></i>
<i class="fa fa-star" aria-hidden="true" id="hs4"></i>
<i class="fa fa-star" aria-hidden="true" id="hs5"></i>
</div>
<p class="hint-text">鼠标划过预览效果,移开后恢复原状</p>
</div>
<script>
$(document).ready(function () {
// 悬停第 1 颗星
$("#hs1").hover(function () {
$(".fa-star").css("color", "#ccc");
$("#hs1").css("color", "#f5a623");
});
// 悬停第 2 颗星
$("#hs2").hover(function () {
$(".fa-star").css("color", "#ccc");
$("#hs1, #hs2").css("color", "#f5a623");
});
// 悬停第 3 颗星
$("#hs3").hover(function () {
$(".fa-star").css("color", "#ccc");
$("#hs1, #hs2, #hs3").css("color", "#f5a623");
});
// 悬停第 4 颗星
$("#hs4").hover(function () {
$(".fa-star").css("color", "#ccc");
$("#hs1, #hs2, #hs3, #hs4").css("color", "#f5a623");
});
// 悬停第 5 颗星
$("#hs5").hover(function () {
$(".fa-star").css("color", "#ccc");
$("#hs1, #hs2, #hs3, #hs4, #hs5").css("color", "#f5a623");
});
});
</script>
</body>
</html>
鼠标依次划过星标时,对应数量的星星会亮起金色;鼠标移开后颜色保持在当前悬停状态。hover() 方法实际上绑定了 mouseenter 和 mouseleave 两个事件,这里只传入了 mouseenter 的回调,所以移开后不会自动重置。
本节课程知识要点
-
先重置再点亮:每次操作的第一步是用
$(".fa-star").css("color", "#ccc")将所有星标置为灰色,保证上次操作的状态被清除,再按需点亮目标星标。 -
ID 组合选择器:
$("#st1, #st2, #st3")用逗号分隔多个 ID,一次性选中多个元素应用相同样式,减少代码冗余。 -
click 与 hover 的场景分工:
click用于确定性的评分记录,hover用于临时预览。两者也可结合——悬停时预览效果,点击时锁定分值。 -
hover 只绑 mouseenter 的后果:如果
hover()只传一个函数参数,它只作用于mouseenter,移开后不会自动恢复。需要恢复效果时,应传入第二个回调函数或将初始状态命名为 class 并用mouseleave重置。
个人经验与优化建议
上面两个示例展示了基础逻辑,但在生产环境中还有几个值得改进的点。
第一,减少重复代码。当前代码为每颗星写了一段几乎相同的逻辑,5 颗星 5 段,扩展到 10 颗星就会很难维护。更好的做法是用一个循环或利用 DOM 遍历关系:点击某颗星时,通过 .prevAll() 找到前面的所有星标,加上自己,统一添加高亮类,后面的星标统一移除高亮类。这样无论多少颗星,核心代码只需要一段。
第二,使用 CSS 类而不是内联样式。示例中直接用 .css() 设置颜色,不利于主题切换。定义一个 .active 类集中管理高亮样式,jQuery 只负责切换类名(用 .addClass() 和 .removeClass()),职责更清晰。
第三,hover 模式下鼠标离开整个评分区域时应恢复到上次的点击值或清除预览。可以在评分区域的外层容器上绑定 mouseleave 事件,当鼠标离开评分区时恢复到一个已知状态。这对用户体验的提升很明显——悬停只是“试用”,离开后应该回到“当前已选”或“未选”状态。
如果你想把这个组件真正用在项目里,建议将其封装为一个接受配置参数的 jQuery 插件,可配置项包括:星标总数、初始选中值、是否只读、回调函数等。这样在不同页面复用时只需要传参,不需要复制代码。