事件冒泡用于简化星星评分交互:通过父容器监听点击,利用event.target识别被点星星并获取data-value,再根据分数高亮对应数量的星星。

事件冒泡本身不是用来“实现”评分星星效果的,而是 JavaScript 事件传播机制中的一环;我们利用它来简化多个星星元素的点击监听——只需给父容器绑定一次点击事件,就能响应所有子星星的点击,再通过事件对象的 target 找到被点中的星星。
结构:用一个容器包裹五个星星
HTML 中用 <div class="star-rating"> 包住五个可点击的 <span> 或 <i> 元素,每个代表一颗星。不给每颗星单独加 onclick,避免重复绑定。
例如:
<div class="star-rating"><span data-value="1">★</span>
<span data-value="2">★</span>
<span data-value="3">★</span>
<span data-value="4">★</span>
<span data-value="5">★</span>
</div>
监听父容器,靠 event.target 识别点击目标
为 .star-rating 添加点击事件监听器。由于点击某颗星时,事件会从该星向上“冒泡”到父容器,我们在父容器的回调里检查 event.target 是否为星星元素,并读取它的 data-value。
立即学习“Java免费学习笔记(深入)”;
关键代码:
ratingEl.addEventListener('click', function (e) {
if (e.target.matches('span[data-value]')) {
const score = Number(e.target.dataset.value);
console.log('选中评分:', score);
// 接下来高亮前 score 颗星(见下一点)
}
});
高亮逻辑:根据评分值统一设置样式
拿到点击的分数后,遍历所有星星,把 data-value ≤ 当前分数 的星星设为实心(比如加 class active),其余设为空心或默认状态。
可以这样写:
function highlightStars(score) {const stars = ratingEl.querySelectorAll('span');
stars.forEach((star, i) => {
const value = Number(star.dataset.value);
if (value star.classList.add('active');
} else {
star.classList.remove('active');
}
});
}
然后在点击回调里调用 highlightStars(score) 即可。
可选增强:支持鼠标悬停预览、点击后锁定
如果想提升体验,可以额外监听 mouseover 实现悬停高亮(不提交)、用 mouseleave 恢复、用一个变量记录是否已点击来防止重复提交。注意:悬停事件也依赖冒泡,但通常直接绑定在星星上更直观;而提交动作仍建议只由父容器统一处理,保持逻辑集中。
不需要阻止冒泡(e.stopPropagation()),否则父容器收不到事件 —— 这正是我们依赖的机制。


















