javascript

Нюансы кроссплатформенной разработки на Vue и React

  • вторник, 8 июля 2025 г. в 00:00:04
https://habr.com/ru/articles/925732/

Этот документ — не просто список, а выжимка боли, шишек и неожиданных открытий, с которыми сталкивается почти каждый фронтендер. Неважно, Vue ты выбрал или React, если твое приложение должно работать в браузере на айфоне пятилетней давности — добро пожаловать в клуб. Здесь будет всё: от странностей с Safari до неожиданных проблем с синтетическими событиями.

Нюансы мобильных браузеров и PWA

iOS Safari не поддерживает Notification API без установки PWA

Проблема: На iOS ты не можешь просто вызвать new Notification(...) — API будет недоступно, пока пользователь не установит сайт как PWA на домашний экран. Так же, в Safari просто не будет доступен класс Notification, браузер его просто не имплиментирует на этапе браузерного окна.

Решение:

- Чтобы проверить можно ли использовать уведомления можно написать следующую проверку:

typeof window !== 'undefined' && 'Notification' in window;

🔗 MDN — Notification API

🔗 WebKit — Push Notifications


Safari не поддерживает input[type="date"] как положено

Проблема: На iOS Safari отображает input[type="date"] как обычное текстовое поле без нативного выбора даты.

Пример:

<!-- Ожидается нативный datepicker, но получаем обычный input -->

<input type="date" />

Решение:

- Использовать кастомные datepickers (например, vue-datepicker, react-datepicker).

- Проверять наличие поддержки через input.type === 'date'.

🔗 caniuse — 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.

🔗 WebKit bug tracker


Safari запрещает getUserMedia() на страницах без HTTPS и без взаимодействия

Проблема: Камера и микрофон через getUserMedia() в iOS Safari не работают, если:

- Страница не под HTTPS

- Не было клика по экрану

Пример:

navigator.mediaDevices

  .getUserMedia({ video: true })

  .then((stream) => {

    // Работа с видео-потоком

  })

  .catch((err) => {

    console.error('Ошибка доступа к камере', err);

  });

Решение:

- Всегда использовать HTTPS

- Запрашивать доступ только по клику пользователя (например, по кнопке)

🔗 MDN — getUserMedia


backdrop-filter работает нестабильно в некоторых Android-браузерах

Проблема: В Chrome на Android backdrop-filter: blur(...) может либо не работать вовсе, либо ломать layout.

Пример:

.glass {

  backdrop-filter: blur(10px);

  background: rgba(255, 255, 255, 0.2);

}

Решение:

- Проверяй поддержку через @supports

- Используй fallback с полупрозрачным цветом

🔗 caniuse — backdrop-filter


Android Chrome игнорирует scrollIntoView({ behavior: 'smooth' }) в iframe

Проблема: Встраиваешь страницу в iframe — smooth scroll больше не работает на Android.

Пример:

document.querySelector('#target').scrollIntoView({ behavior: 'smooth'

Решение:

- В iframe использовать кастомную анимацию прокрутки через JS (window.scrollTo + requestAnimationFrame)

🔗 Stack Overflow discussion


Поведение фреймворков

React генерирует синтетические события, а Vue работает с нативными

Проблема: В Vue компонент работает отлично, но после портирования на React всё ломается: всплытие, отмена событий, или event.currentTarget ведёт себя странно.

Пример: Тултипы в Vue показывались при mouseenter/mouseleave, но в React перестали работать, потому что SyntheticEvent не соответствует MouseEvent полностью.

Решение:

- Используй nativeEvent если нужно добраться до настоящего события.

- Всегда читай React SyntheticEvent

🔗 React Docs — SyntheticEvent