javascript - 有人可以修复我使用 HTML CSS Vanilla Javscript 创建的星级评分(星级只会突出显示以前的元素)
问题描述
我使用 CSS HTML 和 Javascript 创建了一个星级评分应用程序。当我点击一颗星时,它没有按预期突出显示。假设我点击了第三颗星,然后只有两颗星才被突出显示。
我不明白我应该如何处理 css 属性,这将使当前点击的星星突出显示。
let stars = document.querySelectorAll('.star');
document.querySelector('.star-container').addEventListener('click', starRating);
let rating = document.querySelector('.rating');
function starRating(e) {
if (e.target.classList[0] == 'star') {
stars.forEach((star) => star.classList.remove('star__checked'));
for (i = stars.length - 1, j = 0; i >= 0; i--, j++) {
if (stars[i] !== e.target) {
stars[i].classList.add('star__checked');
} else {
stars[i].classList.add('star__checked');
rating.textContent = `${j + 1}/5`;
break;
}
}
} else {
stars.forEach((star) => star.classList.remove('star__checked'));
rating.textContent = `${0}/5`;
}
}
.star-container {
display: flex;
width: 350px;
flex-direction: row-reverse;
}
.star {
}
.star:before {
content: '\f005';
font-family: fontAwesome;
font-size: 60px;
position: relative;
display: block;
color: pink;
}
.star:after {
content: '\f005';
font-family: fontAwesome;
position: absolute;
top: 7px;
font-size: 60px;
color: gold;
opacity: 0;
}
.star:hover:after,
.star:hover ~ .star:after {
opacity: 1;
}
.star__checked ~ .star:after {
opacity: 1;
}
<html lang="en">
<head>
<link rel="stylesheet" href="./styles.css" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<title>Document</title>
</head>
<body>
<div class="star-container">
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
</div>
<h1 class="rating">0/5</h1>
<script src="app.js"></script>
</body>
</html>
解决方案
实际上,您的问题在于这条线:
.star__checked~.star:after {
opacity: 1;
}
这里发生了什么事?
当您应用star__checked
到每个所需元素时,无需为后续兄弟应用样式。~
用于一般的后继兄弟,所以无论何时定义这样的样式,它只会选择后继元素(因为您使用flex-direction: row-reverse;
的元素将从右到左开始,所以它只会突出显示您的后继元素)。因此,您应该只应用带有类的opacity: 1;
for 元素。star__checked
如何解决?
如果要修复当前代码,只需将上述部分替换为以下内容即可:
.star__checked.star:after {
opacity: 1;
}
您的最终代码将是这样的:
let stars = document.querySelectorAll('.star');
document.querySelector('.star-container').addEventListener('click', starRating);
let rating = document.querySelector('.rating');
function starRating(e) {
if (e.target.classList[0] == 'star') {
stars.forEach((star) => star.classList.remove('star__checked'));
for (i = stars.length - 1, j = 0; i >= 0; i--, j++) {
if (stars[i] !== e.target) {
stars[i].classList.add('star__checked');
} else if (stars[i] === e.target) {
stars[i].classList.add('star__checked');
rating.textContent = `${j + 1}/5`;
break;
}
}
} else {
stars.forEach((star) => star.classList.remove('star__checked'));
rating.textContent = `${0}/5`;
}
}
.star-container {
display: flex;
width: 350px;
flex-direction: row-reverse;
}
.star:before {
content: '\f005';
font-family: fontAwesome;
font-size: 60px;
position: relative;
display: block;
color: pink;
}
.star:after {
content: '\f005';
font-family: fontAwesome;
position: absolute;
top: 7px;
font-size: 60px;
color: gold;
opacity: 0;
}
.star:hover:after,
.star:hover~.star:after {
opacity: 1;
}
.star__checked.star:after {
opacity: 1;
}
<html lang="en">
<head>
<link rel="stylesheet" href="./styles.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<title>Document</title>
</head>
<body>
<div class="star-container">
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
</div>
<h1 class="rating">0/5</h1>
<script src="app.js"></script>
</body>
</html>
但是,如果您要寻找最佳实践,则必须使用previousElementSibling
orindexOf()
进行一些进一步的实施和一些魔术,这需要花费大量的工作才能实现,但强烈推荐。
我将给它一个触摸indexOf()
,这个方法将为我们提供数组中当前选定元素的索引。然后我们像往常一样突出显示它,然后~
我们将选择所有后继兄弟姐妹。但请记住,star__checked
该类仅适用于所选元素。
所以它会是这样的:
const stars = document.querySelectorAll('.star');
document.querySelector('.star-container').addEventListener('click', starRating);
const rating = document.querySelector('.rating');
function starRating(e) {
stars.forEach((star) => star.classList.remove('star__checked'));
const i = [...stars].indexOf(e.target);
if (i > -1) {
stars[i].classList.add('star__checked');
rating.textContent = `${stars.length - i}/5`;
} else {
star.classList.remove('star__checked');
rating.textContent = `0/5`;
}
}
.star-container {
display: flex;
width: 350px;
flex-direction: row-reverse;
}
.star:before {
content: '\f005';
font-family: fontAwesome;
font-size: 60px;
position: relative;
display: block;
color: pink;
}
.star:after {
content: '\f005';
font-family: fontAwesome;
position: absolute;
top: 7px;
font-size: 60px;
color: gold;
opacity: 0;
}
.star:hover:after,
.star:hover~.star:after {
opacity: 1;
}
.star.star__checked~.star:after,
.star.star__checked:after {
opacity: 1;
}
<html lang="en">
<head>
<link rel="stylesheet" href="./styles.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
<title>Document</title>
</head>
<body>
<div class="star-container">
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
<div class="star"></div>
</div>
<h1 class="rating">0/5</h1>
<script src="app.js"></script>
</body>
</html>
推荐阅读
- swift - 在后台特定时间启动位置更新 - Swift (watchOS)
- dns - 如何将我的域连接到我的 FTP 服务器?
- bootstrap-4 - Bootstrap 4.3.1 列重新排序 class="order-md-1"
- azure - 如何在 Azure API 管理中自动更新 Web 服务 URL
- r - qwraps2 中的 summary_table 和 R 中的 group_by
- angular - Angular 反应式表单将表单组变成空表单控件
- react-native - React Native - 无效的钩子调用。钩子只能在函数组件的主体内部调用
- google-apps-script - 如果标题包含 x,则 Apps 脚本插入 2 列
- clojure - 允许任意规则顺序的语法
- angular - 无法通过选择读取材料表中未定义的属性“数据”