JS. Как избавиться от повторяющихся строк кода?
Всем привет ;)
Написал код на JS, но меня очень смущает, что он повторяется, хочется его минимизировать.
mobileMenuButton.addEventListener('click', () => {
if (cloneMenu.style.visibility === 'hidden') {
cloneMenu.style.visibility = 'visible';
cloneMenu.style.opacity = '100%';
} else {
cloneMenu.style.visibility = 'hidden';
cloneMenu.style.opacity = '0%';
}
});
header.addEventListener('click', (e) => {
if (e.target === body)
cloneMenu.style.visibility = 'hidden';
cloneMenu.style.opacity = '0%';
});
body.addEventListener('keydown', e => {
if (e.code === "Escape") {
cloneMenu.style.visibility = 'hidden';
cloneMenu.style.opacity = '0%';
}
});
const close = () => {
sF.style.visibility = 'hidden';
sF.style.opacity = '0%';
};
body.addEventListener('click', (e) => {
if (e.target === body)
return close();
});
sF.addEventListener('keydown', e => {
if (e.code === "Escape") {
return close();
}
});
search.addEventListener('click', () => {
if (sF.style.visibility === 'hidden') {
sF.style.visibility = 'visible';
sF.style.opacity = '100%';
setTimeout(() => {
return input.focus();
}, 100);
} else {
return close();
}
});
Прикрепил код, объявление и присвоение переменных есть, но добавлять сюда не стал, т.к. особо это ситуацию не поменяет.
Подскажите, люди добрые, по какому принципу можно этот код уменьшить, привести к каким-то общим конструкциям, которые решали бы задачу нескольких элементов?
Ответы (1 шт):
Очень полезный и важный инструмент программиста -- абстракция. Постарайтесь увидеть общее в коде, который пишите.
Например вам удалось заметить, что строчки
sF.style.visibility = 'hidden';
sF.style.opacity = '0%';
не отдельные и независимые, а представляют из себя функцию close(). И это сократило ваш код, не так ли?
Теперь интересный момент. Строки
cloneMenu.style.visibility = 'hidden';
cloneMenu.style.opacity = '0%';
это тоже close(). Но другого элемента. А вы наверняка знаете, что функции могут принимать аргументы и менять своё поведение в зависимости от этих аргументов.
const close = el => {
el.style.visibility = 'hidden';
el.style.opacity = '0%';
};
Теперь можно закрывать что угодно: close(sF), close(cloneMenu)
Вы можете продолжать это упражнение и заметить, что строки
sF.style.visibility = 'visible';
sF.style.opacity = '100%';
тоже связаны, и это можно было бы назвать open() и даже open(sF).
И даже это не предел абстрагирования! На следующем уровне вы можете заметить, что open и close объединяет то, что они относятся к элементу, объекту вашего интерфейса -- виджету, управляют открытостью и закрытостью виджета. Это ООП.
class Widget {
constructor(el) {
this.el = el;
}
open() {
this.el.style.visibility = 'visible';
this.el.style.opacity = '100%';
}
close() {
this.el.style.visibility = 'hidden';
this.el.style.opacity = '0%';
}
isClosed() {
return this.el.style.visibility === 'hidden';
}
}
После этого ваш код будет приблизительно такой:
mobileMenuButton.addEventListener('click', () => {
if (cloneMenu.isClosed()) {
cloneMenu.open();
} else {
cloneMenu.close();
}
});
header.addEventListener('click', (e) => {
if (e.target === body) {
cloneMenu.close();
}
});
body.addEventListener('keydown', e => {
if (e.code === "Escape") {
cloneMenu.close();
}
});
body.addEventListener('click', (e) => {
if (e.target === body) {
sF.close();
}
});
sF.addEventListener('keydown', e => {
if (e.code === "Escape") {
sF.close();
}
});
search.addEventListener('click', () => {
if (sF.isClosed()) {
sF.open();
setTimeout(() => {
return input.focus();
}, 100);
} else {
sF.close();
}
});
Потом вы можете заметить, что открытие или закрытие виджета, в зависимости от того закрыт ли он или открыт, можно назвать toggle() и снова убрать немного дублирования.
Обработку кликов и нажатий клавиш тоже можно абстрагировать. Но постарайтесь не переусердствовать. Важно вовремя остановится :-)
И прочитайте книгу, которую вам советуют.