n1croo
@n1croo
Front-end developer

Нормальный скрипт для новичка в JS?

Помогите доработать, если что-то не так.
Скрипт для оживления табов.
let tabsBtn = document.querySelectorAll('.services__tabs-item');
let tabsContent = document.querySelectorAll('.services__item');

for (let i = 0; i < tabsBtn.length; i++) {
    tabsBtn[i].addEventListener('click', function(evt) {
        evt.preventDefault();
        compareIndex(i);
    }); 
}

function compareIndex(indexBtn) {
    for (let j = 0; j < tabsContent.length; j++) {
        hideTabs(j);
        if (indexBtn == j) {
            tabsBtn[indexBtn].classList.add('services__tabs-item--active');
            tabsContent[j].classList.add('services__item--active');
        }
    } 
}

function hideTabs(tabsActive) {
    tabsBtn[tabsActive].classList.remove('services__tabs-item--active');
    tabsContent[tabsActive].classList.remove('services__item--active');
}
  • Вопрос задан
  • 245 просмотров
Пригласить эксперта
Ответы на вопрос 2
nikolayshabalin
@nikolayshabalin
Автор профессиональных курсов в HTML Academy
1) Возможно у табов и контента есть один родитель, какой-нибудь .services, тогда лучше через родителя искать детей
let tabsWrapper = document.querySelector('.services');
  let tabsBtn = tabsWrapper.querySelectorAll('.services__tabs-item');
  let tabsContent = tabsWrapper.querySelectorAll('.services__item');


Если всё-таки нет общего родителя, то можно закешировать document. Это всё делается для минимизации трогания DOM, чем меньше тем лучше.

2) Вы в цикле проходитесь по табам и вешаете слушателей. Это не самый лучший вариант, лучше было бы делегировать событие - подробнее тут. По факту вы всегда вешаете одного слушаетеля, а не сколько-то в завимисость от того сколько табов.

3) Если уж es6, то до конца. Применяйте стрелочные функции.
tabsBtn[i].addEventListener('click',  evt => {
       evt.preventDefault();
       compareIndex(i);
   });


4) Не сокращайте название переменных (куда вы деваете время, которое сэкономили на напечатание). Сокращением пускай занимаются роботы - минификаторы, обфускаторы - Вы пишите для людей
evt => event
tabBtn => tabButton
etc.


5) при каждом клике Вы зачем-то проходитесь по всем табам, хотя активным может быть только один таб. Сохраняйте активный таб и как только кликаете на новый, с активного убираете css-классы, а после назначаете кликнутый таб активным.
Ответ написан
dimovich85
@dimovich85 Куратор тега JavaScript
https://u-academy.net/
let tabsBtn = document.querySelectorAll('.services__tabs-item');
let tabsContent = document.querySelectorAll('.services__item');

for (let i = 0; i < tabsBtn.length; i++) {
    tabsBtn[i].addEventListener('click', function(evt) {
        evt.preventDefault();
        for (let j = 0; j < tabsContent.length; j++) {
             tabsBtn[j].classList.remove('services__item--active');
             tabsContent[j].classList.remove('services__tabs-item--active');
         }
        let index = tabsBtn.indexOf(this);
        this.classList.add('services__tabs-item--active');
        tabsContent[index].classList.add('services__item--active');
    }); 
}


По идее, если я все правильно понял, то такой код должен работать.
Суть в том, что иттератор передавать в прослушку события бессмысленно, цикл пройдет и закончится, значение иттератора будет больше длины массива, и это произойдет за доли секунды, а когда пользователь кликнет по табу вызовется функция с иттератором, который будет во-первых всегда статичным, а во-вторых - больше длины массива (иначе, цикл бы продолжался), поэтому Ваш код всегда будет давать андефайнд. Вместо иттератора лучше использовать this, когда человек кликнет на кнопку в this попадет текущая кнопка, по которой кликнули, и мы сначала удаляем активный класс у всех кнопок и контента, а потом текущей кнопке его назначаем. Второе, как я понимаю, что индекс кнопки и индекс таба должен совпадать, иначе код надо будет усложнить. Если индексы совпадают, то создаем локальную переменную, которая вернет индекс кнопки, по которой кликнули, просто находим индекс массива кнопок по объекту this, то есть по кнопке, на которой произошло событие, далее берем этот индекс и находим элемент по этому индексу из массива контента, и ему назначаем активный класс. В результате меньше функций.
Если индексы НЕ совпадают, тогда можно пройтись по всем табам и кнопкам и задать им дата атрибуты, а потом при клике вытаскивать по дата атрибутам нужные элементы и назначать классы, а вот удалять классы, думаю оптимально перед тем, как задать, и удалять классы у всех, а потом активным их задавать.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы