Фронтенд

Практичні матеріали про клієнтську частину вебзастосунків: CSS, JavaScript, Vue.js, побудову інтерфейсів, адаптивність, поведінку браузера та проблеми, які виникають у реальних проєктах. Тут я збираю не абстрактні приклади, а ситуації, які довелося діагностувати й виправляти під час розробки.

telegram-shows-the-open-graph-image-but-linkedin-does-not-debugging-social-preview-caches.png
Фронтенд

Telegram показує Open Graph-зображення, а LinkedIn ні: як діагностувати кеш попереднього перегляду

Одна платформа може вже показувати нове Open Graph-зображення, а інша ще тримати старий попередній перегляд. Це не завжди означає помилку в meta tags. Перевіряти потрібно окремо HTML, SSR, доступність og:image, HTTP-відповідь і кеш конкретного робота.

16
a-click-is-not-a-successful-action-track-analytics-after-the-real-success-boundary.png
Фронтенд

Клік ще не означає успішну дію: коли записувати аналітичну подію

Клік по кнопці "Копіювати посилання" показує намір користувача, але не доводить, що посилання справді потрапило до буфера обміну. Якщо дія може завершитися помилкою, подію успіху варто записувати лише після фактичного завершення операції.

28
why-notification-counters-go-stale-after-returning-to-browser-tab.png
Vue.js

Чому лічильник нотифікацій застаріває після повернення у вкладку

У SPA лічильник unread notifications може бути правильним під час активної роботи й застаріти після sleep, background tab або повернення через browser cache. WebSocket добре доставляє зміни в реальному часі, але після повернення у вкладку state треба звірити з сервером.

47
vue-h-link-slot-function-warning-cover.png
Vue.js

Чому h(Link, ..., 'text') дає попередження Vue: вміст компонента треба передавати функцією

Інтерфейс може виглядати правильно, але Vue все одно попереджає про значення default slot. Причина проста: для компонента третій аргумент h() не варто передавати звичайним рядком. Показую різницю між h('a', ...) і h(Link, ...).

95
reset-pagination-on-filter-change-without-triggering-two-requests-cover.png
Vue.js

Зміна фільтра повинна скидати пагінацію, але не робити подвійний запит

Коли користувач змінює фільтр, поточна сторінка старої вибірки більше не має сенсу. Але просте скидання pageIndex усередині спостерігача може запустити два однакові запити. Розбираю, як розділити ці реакції без дублювання завантаження.

99
vue-nested-links-anchor-inside-anchor-dom-click-behavior-cover.png
Vue.js

Vue nested links на практиці: чому посилання всередині посилання ламає DOM і кліки

У MessageAttachments.vue я зіткнулася з вкладеним <a>: вся картка відкривала вкладення, а окреме посилання всередині мало завантажувати файл. Пояснюю, чому @click.stop не виправляє невалідний HTML, як браузер може перебудувати DOM і чому дві дії краще робити сусідніми елементами.

125
vue-rich-text-editor-drag-drop-editable-content-cover.png
Vue.js

Vue Rich Text Editor і drag-and-drop: чому службовий текст інтерфейсу потрапляв у ContentBlock

Після перетягування Content Blocks у Vue-редакторі службові підписи блока інколи опинялися всередині Rich Text: locale, позиція, ID якоря, назва редактора й інший текст інтерфейсу. Розбираю, чому drag-and-drop поруч із contenteditable потребує стабільних Vue keys, чітких DOM-меж, правильного життєвого циклу редактора та окремого контракту синхронізації контенту.

139
css-stacking-contexts-vue-admin-z-index-cover.png
CSS

CSS Stacking Contexts у Vue-адмінці: чому великий z-index не підняв Media Explorer над Content Blocks

У редакторі ICanUp Media Explorer відкривався поверх Content Blocks, але частина елементів редактора все одно могла опинятися над модальним шаром. Показую, чому великий z-index не завжди вирішує таку проблему, як працюють CSS stacking contexts і чому для overlay потрібен чіткий контракт шарів, а не випадкові числа.

158