Sum*_*ade 1 html javascript css dom ecmascript-6
我使用 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`;
}
}Run Code Online (Sandbox Code Playgroud)
.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;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
实际上你的问题就在这条线后面:
.star__checked~.star:after {
opacity: 1;
}
Run Code Online (Sandbox Code Playgroud)
当您应用star__checked到每个所需的元素时,无需为后续同级元素应用样式。~用于一般后继兄弟,因此每当您定义这样的样式时,它只会选择后继元素(因为您使用flex-direction: row-reverse;的元素将从右到左开始,所以它只会突出显示您的后继元素)。因此,您应该只应用opacity: 1;带有star__checkedclass 的 for 元素。
如果您想修复当前的代码,只需将提到的部分替换为以下内容即可:
.star__checked.star:after {
opacity: 1;
}
Run Code Online (Sandbox Code Playgroud)
你的最终代码将是这样的:
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`;
}
}Run Code Online (Sandbox Code Playgroud)
.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;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
但是,如果您正在寻找最佳实践,则必须使用previousElementSibling或indexOf()进行一些进一步的实施和一些魔法,这需要大量工作才能实现,但强烈建议这样做。
我将使用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`;
}
}Run Code Online (Sandbox Code Playgroud)
.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;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)