Сборная солянка про фронтенд. JavaScript, React, TypeScript, HTML, CSS — здесь обсуждаем всё, что связано с веб-разработкой! Связь: @pmowq
Привет! Сегодня я хочу поговорить о принципе DRY (Don't Repeat Yourself) и поделиться своими мыслями о том, как его правильно применять.
Применение DRY не всегда означает стремление к избавлению от любого дублирования кода. На самом деле, ключ к успешному использованию DRY заключается в понимании, когда и как нужно обобщать код.
Вот простой и эффективный подход к применению DRY:
1. Когда вы сталкиваетесь с новой задачей, начните с решения, нацеленного на конкретный случай. Это позволяет быстрее разработать работающий код и лучше понять задачу.
2. Если похожая задача возникает во второй раз, используйте уже написанный код, адаптируя его под новые условия. Важно здесь отметить в коде, что произошло повторение, чтобы быть осведомленным о потенциальной необходимости в дальнейшем обобщении.
3. Когда вы сталкиваетесь с проблемой в третий раз, это является сигналом к обобщению. Теперь у вас есть достаточно контекста и понимания для создания универсального решения.
Этот подход помогает избежать преждевременной абстракции и усложнения кода. Он также позволяет более глубоко понять проблему, прежде чем переходить к обобщенному решению.
DRY — это не просто правило избегать дублирования кода, а скорее стремление к упрощению и улучшению архитектуры вашего проекта. Помните, что ключевым фактором здесь является баланс: найти золотую середину между частными решениями и обобщенными подходами.
А что вы думаете на счет DRY?
Привет 👋! Начнем эту неделю с задачи, которую я встретил на одном из собеседований. Эта задача может и не является популярной, но она достаточно интересна и имеет разные варианты.
Задача
Представьте, что перед вами банкомат, загруженный купюрами различных номиналов, причем каждого номинала в разном количестве. Ваша задача - выдать заданную сумму, используя купюры наибольшего номинала, при этом учитывая их доступное количество.
Пример
В банкомате имеются: 2 купюры по 5000 рублей, 3 купюры по 1000 рублей, 5 купюр по 500 рублей и 10 купюр по 100 рублей. Пользователь хочет снять 8800 рублей. Каков будет ваш подход к выдаче этой суммы, используя купюры наибольшего номинала, которые доступны в банкомате?
Алгоритм решения:
1. Итерируемся по массиву denominations
.
2. Для каждого номинала определяем, сколько купюр мы можем использовать, чтобы приблизиться к запрашиваемой сумме, не превышая ее.
3. Вычитаем из запрашиваемой суммы соответствующее количество денег и добавляем данные о выданных купюрах в результат.
4. Продолжаем, пока не выдадим всю запрашиваемую сумму или пока не пройдем все доступные номиналы.
Решение:
const denominations = [
[5000, 2],
[1000, 3],
[500, 5],
[100, 10]
];
function withdraw(amount) {
let result = [];
for (let [denom, count] of denominations) {
let usableCount = Math.min(count, Math.floor(amount / denom));
if (usableCount > 0) {
amount -= usableCount * denom;
result.push([denom, usableCount]);
}
if (amount === 0) break;
}
return amount === 0 ? result : null; // Возвращаем null, если не можем выдать всю сумму
}
console.log(withdraw(8800));
Привет! Наконец-то наступила пятница 🍺 Я, как и многие, всегда жду выходные, потому что можно чуть дольше посидеть за компом и не волноваться о том, что просплю дейли. Сейчас, буквально за пару секунд, я поделился с вами частью своих планов на выходные. Так же быстро и легко можно делиться информацией с помощью Web Share API, о котором пойдет речь сегодня.
Что такое Web Share API?
Web Share API - это интерфейс программирования приложений, который позволяет приложениям использовать нативный механизм обмена данных операционной системы. Проще говоря, это позволяет пользователям делиться контентом, таким как текст, ссылки или файлы, напрямую через встроенные в их устройство функции обмена.
Как это работает?
Вызов navigator.share()
открывает нативное диалоговое окно обмена устройства. Этот метод принимает объект, который может содержать 4 свойства:
1. title
- заголовок
2. text
- текст
3. url
- ссылка
4. files
- массив файлов
Пример использования:
const shareData = {
title: '@TrueFrontender',
text: 'Подпишись!',
url: '/channel/TrueFrontender'
};
shareButton.addEventListener('click', () => {
if (!navigator.canShare) {
console.log('Браузер не поддерживает Web Share API')
}
if (navigator.canShare && navigator.canShare(shareData)) {
navigator.share(shareData)
.then(() => console.log('Поделились!'))
.catch((error) => console.log('Ошибка:', error));
} else {
console.log('Браузер не поддерживает Web Share API для данного типа данных.');
}
});
canShare
- этот метод позволяет проверить, поддерживает ли браузер обмен определенными типами данных, что предотвращает возможные ошибки.Привет, дорогие читатели 🤗! Уже наступила среда, а это значит, что половина недели успешно пройдена, и мы стали еще ближе к выходным 🪱
Сегодня хочу вместе с вами базово разобрать методологию BEM (Block, Element, Modifier) и её роль в организации CSS.
Что такое BEM?
BEM разделяет интерфейс на независимые блоки, что упрощает поддержку кода. Он состоит из трёх компонентов:
1. Блок - это независимый компонент интерфейса, например, кнопка или меню.
2. Элемент - это часть блока, выполняющая определённую функцию. Например, пункт в меню.
3. Модификатор - это свойство блока или элемента, определяющее его внешний вид или поведение, например, активный пункт меню.
Пример:
/* Блок */
.menu { ... }
/* Элемент */
.menu__item { ... }
/* Модификатор */
.menu__item_active { ... }
menu__item_disabled
лучше, чем menu__item_gray
.product-card
для карточки товара. Внутри него могут быть элементы как product-card__title
для названия, так и product-card__price
для цены. Если мы хотим выделить карточку товара на распродаже, мы добавляем модификатор product-card_sale
./* Блок */
.product-card { ... }
/* Элементы */
.product-card__title { ... }
.product-card__price { ... }
/* Модификатор */
.product-card_sale { ... }
С понедельником! Сегодня поговорим о паттерне Builder(строитель). Он актуален, когда речь идет о создании сложных интерфейсов. Паттерн помогает разбить процесс на управляемые этапы, делая код чище и более организованным.
Что такое паттерн "Строитель"?
Строитель - это порождающий паттерн проектирования, который позволяет создавать сложные объекты, разделяя их создание на разные этапы. Это полезно, когда объект должен быть создан в несколько этапов или имеет множество возможных конфигураций.
Применение
Паттерн часто применяется для создания сложных UI компонентов. Например, при создании формы с множеством полей, кнопок и валидационных правил. Использование паттерна помогает упростить и структурировать процесс.
Преимущества:
Чистый код - использование этапов в процессе создания обеспечивает повышенную читаемость и облегчает поддержку кода.
Гибкость - возможность добавлять новые этапы и компоненты, не затрагивая уже написанный код.
Изоляция - сложные аспекты создания объектов удобно управляются и инкапсулируются.
Пример реализации
Допустим, у нас есть задача создания сложного интерактивного диалогового окна. Используя паттерн "Строитель", мы можем разделить этот процесс на этапы: создание основного контейнера, добавление кнопок, настройка обработчиков событий и так далее.
Пример с кодом на прикрепленном изображении.
В этом примере:
1. ModalBuilder
- класс, реализующий паттерн "Строитель". Он позволяет пошагово создавать модальное окно с заголовком, содержимым и кнопками.
2. Методы setTitle
, addButton
, и setContent
позволяют задавать соответствующие части модального окна.
3. Метод build
создает и возвращает готовый элемент модального окна, который затем может быть добавлен в DOM.
Заключение
Паттерн "Строитель" является мощным инструментом для упрощения создания сложных объектов. Он обеспечивает чистоту и структурированность кода, делая его более поддерживаемым и расширяемым. Использование этого паттерна поможет вам управлять сложными задачами создания интерфейса и повысит качество вашего кода.
#patterns
С пятницей!
Наконец-то настал вечер пятницы, время, когда можно отдохнуть после долгой рабочей недели 🥳
Я полностью погрузился в работу и медленно, но верно приступаю к разработке большой стори. На выходных планирую уделить время созданию новых постов для вас. Надеюсь, посты на этой неделе были полезными для вас)
А как прошла ваша неделя, и чем вы планируете заниматься на выходных? Делитесь своими историями и планами в комментариях или просто поддержите этот пост реакциями ☺️
Всем хороших выходных 🏝
Всем ✌️! Сегодня я хочу поделиться с вами своими мыслями о !important
в CSS, этой маленькой, но мощной детали, которая часто становится предметом горячих дебатов.
Что такое !important?!important
- это декларация, которая может быть добавлена к стилю, чтобы повысить его приоритет над другими объявлениями. Например:
p {
color: blue !important;
}
<p>
, цвет текста будет синим.!important
.!important
может быть полезным.!important
.!important
.!important
только как крайнюю меру.!important
.!important
, чтобы облегчить понимание и поддержку кода в будущем.!important
это мощный инструмент, но его использование должно быть обоснованным и ограниченным. Осознанное применение !important
поможет избежать многих проблем, связанных с поддержкой и масштабированием ваших проектов.Приветствую всех! Сегодня мы обсудим одну из фундаментальных тем в CSS - вес селекторов. Это поможет нам понять, как браузер решает, какие стили применять к элементу, когда имеется несколько конкурирующих правил.
Что такое вес селекторов?
Вес селектора определяет приоритетность стилей. Когда несколько селекторов претендуют на изменение одного и того же элемента, в игру вступает вес селекторов. Браузер следует правилам специфичности, чтобы определить, какие стили применять.
Вес селектора определяется на основе трех типов селекторов:
1. ID селекторы (#id
) имеют самый высокий вес.
2. Классы, псевдоклассы и атрибуты (.class
, :hover
, [type="text"]
) следуют за ID по весу.
3. Элементы и псевдоэлементы (например, div
, ::after
) имеют самый низкий вес.
Специфичность селектора можно представить в виде чисел, например: 0,1,0,0 для ID селектора, 0,0,1,0 для класса, и 0,0,0,1 для типа элемента. Но почему используются именно четыре цифры? Это связано с тем, что первая цифра отвечает за инлайновые стили (атрибут style
в HTML), которые имеют самый высокий приоритет.
Правила подсчета:
Специфичность считается слева направо: инлайновые стили, затем ID, классы/псевдоклассы/атрибуты, и в конце элементы/псевдоэлементы. Более специфичный селектор переопределяет менее специфичные, даже если они объявлены позже.
Примеры:
- Селектор #header
(вес 0,1,0,0) переопределит .main .header
(вес 0,0,2,0) из-за наличия ID селектора.
- Селектор .button.active
(вес 0,0,2,0) будет иметь больший приоритет, чем .button
(вес 0,0,1,0) благодаря дополнительному классу.
- Селектор div span
(вес 0,0,0,2) будет менее специфичным, чем .element
(вес 0,0,1,0), несмотря на использование двух типов элементов.
Важные моменты:
- Универсальный селектор (*
), комбинаторы (например, +
, >
) и отрицание (:not()
) не влияют на вес.
- Стили, объявленные в атрибуте style HTML элемента, всегда имеют наивысший приоритет (за исключением !important
).
- Использование !important
в CSS объявлении может переопределить другие стили, независимо от их специфичности, но следует избегать его частого использования. В этом посте(тык) я делился своими мыслями на счет !important
.
Почему это важно?
Понимание веса селекторов критически важно для эффективной работы с CSS. Это помогает в избежании конфликтов стилей и позволяет писать более предсказуемый и управляемый код.
Заключение
Итак, мы разобрали, как браузер определяет, какие стили нужно применить к элементу, на основе веса селекторов. Это знание помогает создавать стили, которые ведут себя ожидаемо и легче поддаются дебаггингу. Понимание специфичности селекторов позволяет вам избегать излишнего использования !important
и обеспечивает более чистый, поддерживаемый код.
#css
Привет! Сегодня рассмотрим простой алгоритм сортировки. Сортировка вставками (Insertion Sort) — один из базовых, но в то же время эффективных алгоритмов сортировки. Этот метод часто используется из-за его простоты и эффективности на небольших массивах данных.
Что такое сортировка вставками?
Сортировка вставками — это алгоритм сортировки, который строит отсортированный массив элемент за элементом, вставляя каждый следующий элемент в подходящее место. Проще говоря, алгоритм берет элемент и вставляет его в правильное место среди уже отсортированных элементов.
Пример из жизни
Представьте, что у вас есть рука, полная игральных карт. Вы берете карту и, просматривая уже отсортированные в руке карты, вставляете ее в нужное место. Точно так же работает сортировка вставками с массивами данных.
Преимущества:
- Простота реализации.
- Хорошая производительность на небольших массивах.
- Эффективна для массивов, которые уже частично отсортированы.
- Не требует дополнительной памяти.
Пример реализации:
function insertionSort(array) {
// Проходим по массиву, начиная со второго элемента,
// так как первый элемент уже считается отсортированным
for (let currentIndex = 1; currentIndex < array.length; currentIndex++) {
let currentValue = array[currentIndex]; // Текущий элемент для вставки
let previousIndex = currentIndex - 1; // Индекс предыдущего элемента
// Идём назад по массиву и ищем подходящее место для текущего элемента.
// Элементы, которые больше текущего значения, сдвигаем на один шаг вправо.
while (previousIndex >= 0 && array[previousIndex] > currentValue) {
array[previousIndex + 1] = array[previousIndex]; // Сдвигаем элемент вправо
previousIndex--; // Переходим к следующему элементу для сравнения
}
// Вставляем текущий элемент в найденную позицию.
array[previousIndex + 1] = currentValue;
}
return array;
}
// Пример использования
console.log(insertionSort([9, 1, 15, 4, 0]));
Всем привет ✌️
В этой статье мы погрузимся в Flexbox - мощный инструмент CSS для создания гибких и адаптивных макетов. Рассмотрим основные понятия и ключевые свойства.
-> Читать статью
#css
Всем привет! Хочу вместе с вами разобрать интересную задачу с собеседований: создание функции sum
, которая позволяет выполнять цепочку вызовов вида sum(1)(2, 4)(3)
и так далее. Эта задача является отличным тестом на понимание работы замыканий в JavaScript.
Требования к функции:
1. Функция должна корректно обрабатывать несколько последовательных вызовов с любым количеством аргументов.
2. Каждый вызов функции с аргументами должен добавлять эти значения к общей сумме.
3. Если функция вызвана без аргументов, она должна возвращать текущее значение суммы.
Решение:
function sum(...args) {
let total = args.reduce((acc, cur) => acc + cur, 0);
function innerSum(...innerArgs) {
if (!innerArgs.length) return total;
total += innerArgs.reduce((acc, cur) => acc + cur, 0);
return innerSum;
}
return innerSum;
}
innerSum
вызывается без аргументов, она возвращает накопленный результат.
console.log(sum(1)(2, 4)(3)()); // Выведет 10
Привет всем! Вероятно, вы уже прочитали множество статей о git, но я хочу предложить вам прочитать еще и мой пост) Сегодня я поделюсь своими мыслями о лучших практиках, а также предоставлю вам пару ссылок на интересные ресурсы.
Что такое Git?
Git - это система управления версиями, позволяющая отслеживать изменения в файлах и координировать работу над ними между несколькими людьми. Основное преимущество Git - его распределенная природа, позволяющая каждому участнику проекта иметь свою локальную копию репозитория.
Лучшие практики использования Git:
- Регулярно сохраняйте изменения, делая мелкие коммиты. Это упрощает навигацию по истории изменений и откат к более ранним версиям при необходимости.
- Пишите понятные и подробные сообщения к коммитам. Описательные сообщения помогают другим членам команды понять сделанные изменения и причины этих изменений.
- Работайте в отдельных ветках для новых функций или исправлений. Это предотвращает возможные конфликты в основной ветке кода и способствует более организованной работе.
- Понимайте разницу между merge
и rebase
для эффективного объединения изменений. merge
соединяет ветки, сохраняя историю изменений, в то время как rebase
переформатирует историю для более чистой линейной последовательности.
- Используйте файл .gitignore
для исключения временных или локальных файлов из репозитория. Это предотвращает добавление ненужных или конфиденциальных файлов в общий репозиторий.
Полезные ссылки:
1. Learn Git Branching - интерактивный туториал, который помогает понять концепции ветвления и слияния в git.
2. Visualizing Git - можно посмотреть, как команды git влияют на структуру репозитория. Отлично подходит для визуализации сложных процессов в git.
#git
Привет! Сегодня хочу разобрать пользовательские события в JavaScript. Узнаем как эти события работают и как мы можем их использовать.
Что такое пользовательское событие?
Пользовательское событие - это событие, которое определено разработчиком, в отличие от стандартных событий, таких как click
, mouseover
и т.д. Это позволяет создавать более сложные и специфические сценарии взаимодействия в приложении.
Как создать пользовательское событие?
1. Использование конструктора Event
. Это базовый способ создания пользовательских событий.
const event = new Event('customEvent', {
bubbles: true, // Событие всплывает
cancelable: true // Событие можно отменить
});
// Добавление слушателя для события
document.addEventListener('customEvent', function(e) {
console.log('Пользовательское событие активировано');
});
// Инициирование события
document.dispatchEvent(event);
CustomEvent
. CustomEvent
- это расширение Event
, которое позволяет передавать дополнительные данные с событием.const customEvent = new CustomEvent('customEvent', {
detail: { message: 'Привет от CustomEvent' },
bubbles: true,
cancelable: true
});
document.addEventListener('customEvent', function(e) {
console.log('Сообщение: ', e.detail.message);
});
document.dispatchEvent(customEvent);
Разница между useEffect и useLayoutEffect в React
Хуки useEffect
и useLayoutEffect
в React часто вызывают путаницу из-за их схожести. Оба хука предназначены для выполнения побочных эффектов в функциональных компонентах, но они имеют ключевые различия в тайминге их выполнения.
useEffectuseEffect
используется для выполнения побочных эффектов в компоненте, таких как запросы данных, подписки или ручные изменения в DOM, которые не требуют немедленного выполнения и не блокируют визуальные обновления.
Особенности:
- Выполняется после отрисовки и коммита компонента в DOM.
- Не блокирует визуальные обновления, что делает его идеальным для большинства побочных эффектов.
- Используется для взаимодействий с внешними API и выполнения асинхронных операций.
useLayoutEffectuseLayoutEffect
работает аналогично useEffect
, но вызывается синхронно после всех изменений DOM, но перед перерисовкой на экране. Это значит, что все изменения, выполненные в useLayoutEffect
, будут отражены на экране сразу после его выполнения.
Особенности:
- Выполняется синхронно после всех изменений DOM, но до перерисовки.
- Используется для чтения или изменения DOM до того, как пользователь увидит обновления.
- Может вызывать блокировку визуальных обновлений, если содержит тяжелые вычисления.
Ключевые различия:
- useEffect
выполняется после отрисовки компонента, позволяя выполнять побочные эффекты без блокировки визуальных обновлений, в то время как useLayoutEffect
выполняется непосредственно после изменений в DOM и перед перерисовкой, что идеально подходит для задач, требующих немедленного чтения или изменения DOM.
- Использование useLayoutEffect
может привести к заметным задержкам в визуальных обновлениях, особенно если в нем содержатся тяжелые вычисления, тогда как useEffect
не оказывает такого влияния на процесс рендеринга.
- В большинстве случаев предпочтительнее использовать useEffect
для обработки побочных эффектов, а useLayoutEffect
следует использовать только тогда, когда необходимо синхронно взаимодействовать с DOM, например для измерения размеров элемента перед его отображением.
Заключение
Выбор между useEffect
и useLayoutEffect
зависит от требований к побочным эффектам в вашем компоненте. Хотя useEffect
является наиболее часто используемым хуком для побочных эффектов из-за его не блокирующего поведения, useLayoutEffect
предоставляет необходимую синхронность для определенных сценариев работы с DOM. Важно правильно выбирать между ними, чтобы обеспечить эффективную работу приложения и хороший пользовательский опыт.
#react