Я хотел бы знать, как я могу сделать код короче, не повторяя все в основном 4 раза (каждый для каждого отдельного элемента .section1). Я хотел бы знать, есть ли синтаксис или что-то, что могло бы сделать код более чистым и, прежде всего, не таким избыточным. Я очень новичок в JS, и я хотел бы узнать больше о нем и о том, как я могу сделать его более оптимизированным.
const section1Card1 = document.querySelector(
".section1-col:nth-of-type(1) .section1-item:nth-child(1)"
);
const section1Card2 = document.querySelector(
".section1-col:nth-of-type(1) .section1-item:nth-child(2)"
);
const section1Card3 = document.querySelector(
".section1-col:nth-of-type(3) .section1-item:nth-child(1)"
);
const section1Card4 = document.querySelector(
".section1-col:nth-of-type(3) .section1-item:nth-child(2)"
);
//
const section1Card1Img = document.querySelector(
".section1-col:nth-of-type(1) .section1-item:nth-child(1) img"
);
const section1Card2Img = document.querySelector(
".section1-col:nth-of-type(1) .section1-item:nth-child(2) img"
);
const section1Card3Img = document.querySelector(
".section1-col:nth-of-type(3) .section1-item:nth-child(1) img"
);
const section1Card4Img = document.querySelector(
".section1-col:nth-of-type(3) .section1-item:nth-child(2) img"
);
//
const cardIndexDot1 = document.querySelector(".image-index-dot:nth-of-type(1)");
const cardIndexDot2 = document.querySelector(".image-index-dot:nth-of-type(2)");
const cardIndexDot3 = document.querySelector(".image-index-dot:nth-of-type(3)");
const cardIndexDot4 = document.querySelector(".image-index-dot:nth-of-type(4)");
//
const section1Cards = document.querySelectorAll(".section1-item");
const section1CardsImg = document.querySelectorAll(".section1-item img");
section1Card1.addEventListener("click", () => {
console.info("bon");
if (!section1Card1.classList.contains("active-card")) {
section1Card2.classList.remove("active-card");
section1Card3.classList.remove("active-card");
section1Card4.classList.remove("active-card");
section1CardsImg.src = "images/tcheen-logo-white.png";
section1Card1.classList.add("active-card");
section1Card1Img.src = "images/tcheen-logo-jaune.png";
cardIndexDot1.classList.add("image-index-dot-active");
cardIndexDot2.classList.remove("image-index-dot-active");
cardIndexDot3.classList.remove("image-index-dot-active");
cardIndexDot4.classList.remove("image-index-dot-active");
console.info("oui");
}
});
section1Card2.addEventListener("click", () => {
console.info("bon");
if (!section1Card2.classList.contains("active-card")) {
section1Card1.classList.remove("active-card");
section1Card3.classList.remove("active-card");
section1Card4.classList.remove("active-card");
section1CardsImg.src = "images/tcheen-logo-blanc.png";
section1Card2.classList.add("active-card");
section1Card2Img.src = "images/tcheen-logo-jaune.png";
cardIndexDot2.classList.add("image-index-dot-active");
cardIndexDot1.classList.remove("image-index-dot-active");
cardIndexDot3.classList.remove("image-index-dot-active");
cardIndexDot4.classList.remove("image-index-dot-active");
console.info("oui");
}
});
section1Card3.addEventListener("click", () => {
console.info("bon");
if (!section1Card3.classList.contains("active-card")) {
section1Card1.classList.remove("active-card");
section1Card2.classList.remove("active-card");
section1Card4.classList.remove("active-card");
section1CardsImg.src = "images/tcheen-logo-blanc.png";
section1Card3.classList.add("active-card");
section1Card3Img.src = "images/tcheen-logo-jaune.png";
cardIndexDot3.classList.add("image-index-dot-active");
cardIndexDot2.classList.remove("image-index-dot-active");
cardIndexDot1.classList.remove("image-index-dot-active");
cardIndexDot4.classList.remove("image-index-dot-active");
console.info("oui");
}
});
section1Card4.addEventListener("click", () => {
console.info("bon");
if (!section1Card4.classList.contains("active-card")) {
section1Card1.classList.remove("active-card");
section1Card2.classList.remove("active-card");
section1Card3.classList.remove("active-card");
section1CardsImg.src = "images/tcheen-logo-blanc.png";
section1Card4.classList.add("active-card");
section1Card4Img.src = "images/tcheen-logo-jaune.png";
cardIndexDot4.classList.add("image-index-dot-active");
cardIndexDot2.classList.remove("image-index-dot-active");
cardIndexDot3.classList.remove("image-index-dot-active");
cardIndexDot1.classList.remove("image-index-dot-active");
console.info("oui");
}
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins";
}
:root {
--color-yellow: #efd858;
--color-pink: #eebcd8;
--color-green: #6cbe99;
--color-black: #1a1a1a;
--color-white: #ffffff;
}
html {
scroll-behavior: smooth;
}
/* */
.yellow-bg {
background-color: var(--color-yellow);
}
img {
width: 100%;
}
/* */
.section1 {
position: relative;
display: flex;
justify-content: center;
gap: 40px;
padding-top: 98px;
}
.section1-col {
width: 20%;
}
.section1-img {
width: 27%;
}
.section1-img img {
border-radius: 10px;
}
.section1-item {
padding: 30px 18px 80px;
position: relative;
border-radius: 10px;
background: var(--color-green);
}
.section1-item:nth-of-type(odd) {
margin-bottom: 15px;
}
.section1-item img {
position: absolute;
display: inline-block;
top: 18px;
right: 18px;
width: 12.5%;
}
.section1-item h3 {
font-weight: 500;
font-size: 20px;
line-height: 26px;
width: 75%;
}
.section1-item p {
font-weight: 400;
font-size: 16px;
line-height: 26px;
}
.image-index {
position: absolute;
bottom: -36px;
width: 120px;
display: flex;
justify-content: space-between;
}
.image-index-dot {
width: 15px;
aspect-ratio: 1;
border-radius: 100%;
background: var(--color-black);
}
/* */
.active-card {
background: var(--color-yellow);
}
.image-index-dot-active {
background: var(--color-yellow);
}
<section class = "section1">
<div class = "section1-col">
<article class = "section1-item active-card">
<img src = "images/tcheen-logo-jaune.png" alt = "Tcheen Logo">
<h3>Eco-responsable et original</h3>
<p>La crème des prestataires sensibilisés à l’engagement durable.</p>
</article>
<article class = "section1-item">
<img src = "images/tcheen-logo-blanc.png" alt = "Tcheen Logo">
<h3>Devis instantané</h3>
<p>Obtenez le match parfait et votre devis en 2 minutes chrono !</p>
</article>
</div>
<div class = "section1-img">
<img src = "https://source.unsplash.com/random/390x500/?space,planet" alt = "Image 1">
</div>
<div class = "section1-col">
<article class = "section1-item">
<img src = "images/tcheen-logo-blanc.png" alt = "Tcheen Logo">
<h3>100% Transparent</h3>
<p>Nos frais de service sont transparents et sans surcoût sur vos prestations.</p>
</article>
<article class = "section1-item">
<img src = "images/tcheen-logo-blanc.png" alt = "Tcheen Logo">
<h3>Accompagnement personnalisé</h3>
<p>Nous vous accompagnons de A à Z avant et pendant votre événement.</p>
</article>
</div>
<div class = "image-index">
<div class = "image-index-dot image-index-dot-active"></div>
<div class = "image-index-dot"></div>
<div class = "image-index-dot"></div>
<div class = "image-index-dot"></div>
</div>
</section>
Это должно сблизить вас. На самом деле я не тестировал этот код, потому что у меня не было html.
const cards = document.querySelectorAll(".section1-item");
const cardImages = document.querySelectorAll(".section1-item img");
const cardDots = document.querySelectorAll(".image-index-dot");
for (let [index, card] of cards.entries()) {
card.addEventListener("click", () => {
console.info("bon");
if (!card.classList.contains("active-card")) {
// remove the class from all the cards
for (let innerCard of cards) {
innerCard.classList.remove("active-card");
}
// not sure why the img src is being set twice
cardImages[index].src = "images/tcheen-logo-white.png";
card.classList.add("active-card");
cardImages[index].src = "images/tcheen-logo-jaune.png";
for (let dot of cardDots) {
dot.classList.add("image-index-dot-active");
}
cardDots[index].add("image-index-dot-active");
}
});
}
Спасибо за ваш ответ, однако, похоже, он не работает. Я отредактировал свой пост, чтобы добавить больше информации и добавить HTML и CSS, чтобы вы могли наглядно увидеть, с чем я работаю. Надеюсь, с вашей помощью мы найдем решение :)
Похоже, что другие предлагаемые решения должны решить вашу проблему.
Да, спасибо, что пытаетесь мне помочь!
.section1-item
и добавьте к нему прослушиватель кликов..active-class
из всех .section1-item
элементов..active-class
к выбранному элементу.section
и вместо этого добавил ::before в CSS.const section1Cards = document.querySelectorAll(".section1-item");
for (section1Card of section1Cards) {
section1Card.addEventListener("click", (event) => {
let clickedCard = event.currentTarget;
for (_secCard of section1Cards) {
_secCard.classList.remove('active-card');
}
clickedCard.classList.add('active-card');
})
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins";
}
:root {
--color-yellow: #efd858;
--color-pink: #eebcd8;
--color-green: #6cbe99;
--color-black: #1a1a1a;
--color-white: #ffffff;
}
html {
scroll-behavior: smooth;
}
/* */
.yellow-bg {
background-color: var(--color-yellow);
}
img {
width: 100%;
}
/* */
.section1 {
position: relative;
display: flex;
justify-content: center;
gap: 40px;
padding-top: 98px;
}
.section1-col {
width: 20%;
}
.section1-img {
width: 27%;
}
.section1-img img {
border-radius: 10px;
}
.section1-item {
padding: 30px 18px 80px;
position: relative;
border-radius: 10px;
background: var(--color-green);
}
.section1-item:nth-of-type(odd) {
margin-bottom: 15px;
}
.section1-item h3 {
font-weight: 500;
font-size: 20px;
line-height: 26px;
width: 75%;
}
.section1-item p {
font-weight: 400;
font-size: 16px;
line-height: 26px;
}
.image-index {
position: absolute;
bottom: -36px;
width: 120px;
display: flex;
justify-content: space-between;
}
.image-index-dot {
width: 15px;
aspect-ratio: 1;
border-radius: 100%;
background: var(--color-black);
}
.active-card {
background: var(--color-yellow);
}
/* ADDED */
.section1-item::before {
content: url('https://via.placeholder.com/90x90.png?text=Blanc');
position: absolute;
display: inline-block;
top: 18px;
right: 18px;
width: 12.5%;
}
/* ADDED */
.section1-item.active-card::before {
content: url('https://via.placeholder.com/90/8f8.png/000/?text=Jaune');
}
.image-index-dot-active {
background: var(--color-yellow);
}
<section class = "section1">
<div class = "section1-col">
<article class = "section1-item active-card">
<h3>Eco-responsable et original</h3>
<p>La crème des prestataires sensibilisés à l’engagement durable.</p>
</article>
<article class = "section1-item">
<h3>Devis instantané</h3>
<p>Obtenez le match parfait et votre devis en 2 minutes chrono !</p>
</article>
</div>
<div class = "section1-img">
<img src = "https://source.unsplash.com/random/390x500/?space,planet" alt = "Image 1">
</div>
<div class = "section1-col">
<article class = "section1-item">
<h3>100% Transparent</h3>
<p>Nos frais de service sont transparents et sans surcoût sur vos prestations.</p>
</article>
<article class = "section1-item">
<h3>Accompagnement personnalisé</h3>
<p>Nous vous accompagnons de A à Z avant et pendant votre événement.</p>
</article>
</div>
<div class = "image-index">
<div class = "image-index-dot image-index-dot-active"></div>
<div class = "image-index-dot"></div>
<div class = "image-index-dot"></div>
<div class = "image-index-dot"></div>
</div>
</section>
Приведенный выше код заботится только о разделах. Я хотел бы воспользоваться возможностью, чтобы показать, как добавлять/удалять классы с помощью querySelect вместо того, чтобы перебирать все элементы .image-index-dot
, как я делал с .section1-item
.
const section1Cards = document.querySelectorAll(".section1-item");
for (let section1Card of section1Cards) {
section1Card.addEventListener("click", (event) => {
let clickedCard = event.currentTarget;
let index = 0, startsCountAtOne = 1;
let activeCardClass = 'active-card';
let activeDotClass = 'image-index-dot-active';
for (let [_index, _secCard] of section1Cards.entries()) {
if (_secCard !== clickedCard) {
_secCard.classList.remove(activeCardClass);
} else {
_secCard.classList.add(activeCardClass);
index = _index + startsCountAtOne;
}
}
let activeDot = document.querySelector('.image-index > .' + activeDotClass);
let clickedDot = document.querySelector(`.image-index > :nth-child(${index})`)
activeDot.classList.remove(activeDotClass);
clickedDot.classList.add(activeDotClass);
})
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins";
}
:root {
--color-yellow: #efd858;
--color-pink: #eebcd8;
--color-green: #6cbe99;
--color-black: #1a1a1a;
--color-white: #ffffff;
}
html {
scroll-behavior: smooth;
}
/* */
.yellow-bg {
background-color: var(--color-yellow);
}
img {
width: 100%;
}
/* */
.section1 {
position: relative;
display: flex;
justify-content: center;
gap: 40px;
padding-top: 98px;
}
.section1-col {
width: 20%;
}
.section1-img {
width: 27%;
}
.section1-img img {
border-radius: 10px;
}
.section1-item {
padding: 30px 18px 80px;
position: relative;
border-radius: 10px;
background: var(--color-green);
}
.section1-item:nth-of-type(odd) {
margin-bottom: 15px;
}
.section1-item h3 {
font-weight: 500;
font-size: 20px;
line-height: 26px;
width: 75%;
}
.section1-item p {
font-weight: 400;
font-size: 16px;
line-height: 26px;
}
.image-index {
position: absolute;
bottom: -36px;
width: 120px;
display: flex;
justify-content: space-between;
}
.image-index-dot {
width: 15px;
aspect-ratio: 1;
border-radius: 100%;
background: var(--color-black);
}
.active-card {
background: var(--color-yellow);
}
/* ADDED */
.section1-item::before {
content: url('https://via.placeholder.com/90x90.png?text=Blanc');
position: absolute;
display: inline-block;
top: 18px;
right: 18px;
width: 12.5%;
}
/* ADDED */
.section1-item.active-card::before {
content: url('https://via.placeholder.com/90/8f8.png/000/?text=Jaune');
}
.image-index-dot-active {
background: var(--color-yellow);
}
<section class = "section1">
<div class = "section1-col">
<article class = "section1-item active-card">
<h3>Eco-responsable et original</h3>
<p>La crème des prestataires sensibilisés à l’engagement durable.</p>
</article>
<article class = "section1-item">
<h3>Devis instantané</h3>
<p>Obtenez le match parfait et votre devis en 2 minutes chrono !</p>
</article>
</div>
<div class = "section1-img">
<img src = "https://source.unsplash.com/random/390x500/?space,planet" alt = "Image 1">
</div>
<div class = "section1-col">
<article class = "section1-item">
<h3>100% Transparent</h3>
<p>Nos frais de service sont transparents et sans surcoût sur vos prestations.</p>
</article>
<article class = "section1-item">
<h3>Accompagnement personnalisé</h3>
<p>Nous vous accompagnons de A à Z avant et pendant votre événement.</p>
</article>
</div>
<div class = "image-index">
<div class = "image-index-dot image-index-dot-active"></div>
<div class = "image-index-dot"></div>
<div class = "image-index-dot"></div>
<div class = "image-index-dot"></div>
</div>
</section>
Вот еще один сокращенный способ сделать это.
Метод element.classList.toggle()
добавляет или удаляет указанное className в classList элемента, в зависимости от того, является ли второй аргумент правдивым или нет.
const [items,dots]=[".section1-item",".image-index-dot"].map(cls=>document.querySelectorAll(cls));
items.forEach(itm=>
itm.addEventListener("click",ev=>{
items.forEach((it,i)=>{
it.classList.toggle("active-card",it===itm);
dots[i].classList.toggle("image-index-dot-active",it===itm);
});
})
);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins";
}
:root {
--color-yellow: #efd858;
--color-pink: #eebcd8;
--color-green: #6cbe99;
--color-black: #1a1a1a;
--color-white: #ffffff;
}
html {
scroll-behavior: smooth;
}
/* */
.yellow-bg {
background-color: var(--color-yellow);
}
img {
width: 100%;
}
/* */
.section1 {
position: relative;
display: flex;
justify-content: center;
gap: 40px;
padding-top: 98px;
}
.section1-col {
width: 20%;
}
.section1-img {
width: 27%;
}
.section1-img img {
border-radius: 10px;
}
.section1-item {
padding: 30px 18px 80px;
position: relative;
border-radius: 10px;
background: var(--color-green);
}
.section1-item:nth-of-type(odd) {
margin-bottom: 15px;
}
.section1-item img {
position: absolute;
display: inline-block;
top: 18px;
right: 18px;
width: 12.5%;
}
.section1-item h3 {
font-weight: 500;
font-size: 20px;
line-height: 26px;
width: 75%;
}
.section1-item p {
font-weight: 400;
font-size: 16px;
line-height: 26px;
}
.image-index {
position: absolute;
bottom: -36px;
width: 120px;
display: flex;
justify-content: space-between;
}
.image-index-dot {
width: 15px;
aspect-ratio: 1;
border-radius: 100%;
background: var(--color-black);
}
/* */
.active-card {
background: var(--color-yellow);
}
.image-index-dot-active {
background: var(--color-yellow);
}
<section class = "section1">
<div class = "section1-col">
<article class = "section1-item active-card">
<img src = "images/tcheen-logo-jaune.png" alt = "Tcheen Logo">
<h3>Eco-responsable et original</h3>
<p>La crème des prestataires sensibilisés à l’engagement durable.</p>
</article>
<article class = "section1-item">
<img src = "images/tcheen-logo-blanc.png" alt = "Tcheen Logo">
<h3>Devis instantané</h3>
<p>Obtenez le match parfait et votre devis en 2 minutes chrono !</p>
</article>
</div>
<div class = "section1-img">
<img src = "https://source.unsplash.com/random/390x500/?space,planet" alt = "Image 1">
</div>
<div class = "section1-col">
<article class = "section1-item">
<img src = "images/tcheen-logo-blanc.png" alt = "Tcheen Logo">
<h3>100% Transparent</h3>
<p>Nos frais de service sont transparents et sans surcoût sur vos prestations.</p>
</article>
<article class = "section1-item">
<img src = "images/tcheen-logo-blanc.png" alt = "Tcheen Logo">
<h3>Accompagnement personnalisé</h3>
<p>Nous vous accompagnons de A à Z avant et pendant votre événement.</p>
</article>
</div>
<div class = "image-index">
<div class = "image-index-dot image-index-dot-active"></div>
<div class = "image-index-dot"></div>
<div class = "image-index-dot"></div>
<div class = "image-index-dot"></div>
</div>
</section>
Вы можете сократить JS до нескольких строк, используя более общий подход.
Вы можете найти коллекцию всех этих статей, выбрав их класс, а затем просмотрев их все, добавив прослушиватель событий щелчка.
Когда вы запускаете прослушиватель, он знает индекс элемента, по которому щелкнули, и поэтому может добавить активный класс и соответствующее изображение логотипа, а также добавить правильный класс к соответствующей точке.
const items = document.querySelectorAll('.section1 > .section1-col .section1-item');
const dots = document.querySelectorAll('.section1 > .image-index > .image-index-dot');
for (let i = 0; i < items.length; i++) {
items[i].addEventListener('click', function () {
for (let j = 0; j < items.length; j++) {
items[j].classList.remove('active-card');
items[j].querySelector('img').src = 'images/tcheen-logo-blanc.png';
dots[j].classList.remove('image-index-dot-active');
}
items[i].classList.add('active-card');
items[i].querySelector('img').src = 'images/tcheen-logo-jaune.png';
dots[i].classList.add('image-index-dot-active');
});
}
Вот полный фрагмент, который не изменяет ваш CSS или ваш HTML:
const items = document.querySelectorAll('.section1 > .section1-col .section1-item');
const dots = document.querySelectorAll('.section1 > .image-index > .image-index-dot');
for (let i = 0; i < items.length; i++) {
items[i].addEventListener('click', function() {
for (let j = 0; j < items.length; j++) {
items[j].classList.remove('active-card');
items[j].querySelector('img').src = 'images/tcheen-logo-blanc.png';
dots[j].classList.remove('image-index-dot-active');
}
items[i].classList.add('active-card');
items[i].querySelector('img').src = 'images/tcheen-logo-jaune.png';
dots[i].classList.add('image-index-dot-active');
});
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins";
}
:root {
--color-yellow: #efd858;
--color-pink: #eebcd8;
--color-green: #6cbe99;
--color-black: #1a1a1a;
--color-white: #ffffff;
}
html {
scroll-behavior: smooth;
}
/* */
.yellow-bg {
background-color: var(--color-yellow);
}
img {
width: 100%;
}
/* */
.section1 {
position: relative;
display: flex;
justify-content: center;
gap: 40px;
padding-top: 98px;
}
.section1-col {
width: 20%;
}
.section1-img {
width: 27%;
}
.section1-img img {
border-radius: 10px;
}
.section1-item {
padding: 30px 18px 80px;
position: relative;
border-radius: 10px;
background: var(--color-green);
}
.section1-item:nth-of-type(odd) {
margin-bottom: 15px;
}
.section1-item img {
position: absolute;
display: inline-block;
top: 18px;
right: 18px;
width: 12.5%;
}
.section1-item h3 {
font-weight: 500;
font-size: 20px;
line-height: 26px;
width: 75%;
}
.section1-item p {
font-weight: 400;
font-size: 16px;
line-height: 26px;
}
.image-index {
position: absolute;
bottom: -36px;
width: 120px;
display: flex;
justify-content: space-between;
}
.image-index-dot {
width: 15px;
aspect-ratio: 1;
border-radius: 100%;
background: var(--color-black);
}
/* */
.active-card {
background: var(--color-yellow);
}
.image-index-dot-active {
background: var(--color-yellow);
}
<section class = "section1">
<div class = "section1-col">
<article class = "section1-item active-card">
<img src = "images/tcheen-logo-jaune.png" alt = "Tcheen Logo">
<h3>Eco-responsable et original</h3>
<p>La crème des prestataires sensibilisés à l’engagement durable.</p>
</article>
<article class = "section1-item">
<img src = "images/tcheen-logo-blanc.png" alt = "Tcheen Logo">
<h3>Devis instantané</h3>
<p>Obtenez le match parfait et votre devis en 2 minutes chrono !</p>
</article>
</div>
<div class = "section1-img">
<img src = "https://source.unsplash.com/random/390x500/?space,planet" alt = "Image 1">
</div>
<div class = "section1-col">
<article class = "section1-item">
<img src = "images/tcheen-logo-blanc.png" alt = "Tcheen Logo">
<h3>100% Transparent</h3>
<p>Nos frais de service sont transparents et sans surcoût sur vos prestations.</p>
</article>
<article class = "section1-item">
<img src = "images/tcheen-logo-blanc.png" alt = "Tcheen Logo">
<h3>Accompagnement personnalisé</h3>
<p>Nous vous accompagnons de A à Z avant et pendant votre événement.</p>
</article>
</div>
<div class = "image-index">
<div class = "image-index-dot image-index-dot-active"></div>
<div class = "image-index-dot"></div>
<div class = "image-index-dot"></div>
<div class = "image-index-dot"></div>
</div>
</section>
</script>
Можете ли вы поделиться с нами своим HTML? Есть очень хороший шанс, что это можно сделать намного проще - как вы просите, - но я ожидаю, что лучший подход (для любого значения «лучшего», которое вы можете определить) будет зависеть от структуры DOM.