Нюансы кроссплатформенной разработки на Vue и React
- вторник, 8 июля 2025 г. в 00:00:04
Этот документ — не просто список, а выжимка боли, шишек и неожиданных открытий, с которыми сталкивается почти каждый фронтендер. Неважно, Vue ты выбрал или React, если твое приложение должно работать в браузере на айфоне пятилетней давности — добро пожаловать в клуб. Здесь будет всё: от странностей с Safari до неожиданных проблем с синтетическими событиями.
iOS Safari не поддерживает Notification API без установки PWA
Проблема: На iOS ты не можешь просто вызвать new Notification(...)
— API будет недоступно, пока пользователь не установит сайт как PWA на домашний экран. Так же, в Safari просто не будет доступен класс Notification, браузер его просто не имплиментирует на этапе браузерного окна.
Решение:
- Чтобы проверить можно ли использовать уведомления можно написать следующую проверку:
typeof window !== 'undefined' && 'Notification' in window;
Safari не поддерживает input[type="date"]
как положено
Проблема: На iOS Safari отображает input[type="date"]
как обычное текстовое поле без нативного выбора даты.
Пример:
<!-- Ожидается нативный datepicker, но получаем обычный input -->
<input type="date" />
Решение:
- Использовать кастомные datepickers (например, vue-datepicker
, react-datepicker
).
- Проверять наличие поддержки через input.type === 'date'
.
iOS Safari не поддерживает position: sticky
внутри overflow: hidden
Проблема: Если ты оборачиваешь блок со position: sticky
в контейнер с overflow: hidden
, то sticky
не работает.
Пример:
.wrapper {
overflow: hidden;
}
.sticky-header {
position: sticky;
top: 0;
}
Решение:
- Либо не задавай overflow: hidden
, либо используй альтернативную реализацию через JS.
Safari запрещает getUserMedia()
на страницах без HTTPS и без взаимодействия
Проблема: Камера и микрофон через getUserMedia()
в iOS Safari не работают, если:
- Страница не под HTTPS
- Не было клика по экрану
Пример:
navigator.mediaDevices
.getUserMedia({ video: true })
.then((stream) => {
// Работа с видео-потоком
})
.catch((err) => {
console.error('Ошибка доступа к камере', err);
});
Решение:
- Всегда использовать HTTPS
- Запрашивать доступ только по клику пользователя (например, по кнопке)
backdrop-filter
работает нестабильно в некоторых Android-браузерах
Проблема: В Chrome на Android backdrop-filter: blur(...)
может либо не работать вовсе, либо ломать layout.
Пример:
.glass {
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.2);
}
Решение:
- Проверяй поддержку через @supports
- Используй fallback с полупрозрачным цветом
Android Chrome игнорирует scrollIntoView({ behavior: 'smooth' })
в iframe
Проблема: Встраиваешь страницу в iframe — smooth scroll больше не работает на Android.
Пример:
document.querySelector('#target').scrollIntoView({ behavior: 'smooth'
Решение:
- В iframe использовать кастомную анимацию прокрутки через JS (window.scrollTo + requestAnimationFrame
)
Поведение фреймворков
React генерирует синтетические события, а Vue работает с нативными
Проблема: В Vue компонент работает отлично, но после портирования на React всё ломается: всплытие, отмена событий, или event.currentTarget
ведёт себя странно.
Пример: Тултипы в Vue показывались при mouseenter
/mouseleave
, но в React перестали работать, потому что SyntheticEvent
не соответствует MouseEvent
полностью.
Решение:
- Используй nativeEvent
если нужно добраться до настоящего события.
- Всегда читай React SyntheticEvent