От Chrome до Safari: обнаружение дубликатов вкладок везде и управление ими
В этом сообщении блога мы рассмотрим фрагмент кода, который можно использовать для проверки наличия дубликатов вкладок в браузере, и расширим его для работы в разных браузерах и платформах с помощью интеграции с сервером.
Введение
Дублирование вкладок может быть проблематичным в определенных сценариях, например при работе с конфиденциальными данными или при попытке поддерживать приложение с одним экземпляром. Обнаружив и предотвратив дублирование вкладок, мы можем обеспечить лучший пользовательский опыт и сохранить целостность данных. Код, который мы будем обсуждать, предоставляет механизм для обнаружения дубликатов вкладок в одном и том же браузере.
Обзор кода
Начнем с изучения фрагмента кода:
import React, { useState, useEffect } from 'react'; import styled from 'styled-components'; const Container = styled.div` padding: 22px 24px 20px; background-color: white; border-radius: 3px; box-shadow: 0 15px 50px 0 rgba(0, 0, 0, 0.19), 0 12px 15px 0 rgba(0, 0, 0, 0.24); position: fixed; top: 40%; left: 50%; transform: translate(-50%); line-height: 1.4rem; width: 400px; `; const ButtonGroup = styled.div` display: flex; align-items: center; justify-content: flex-end; padding-top: 50px; `; const DuplicateTabChecker = ({ children, panelKey, panel }) => { const [duplicateTab, setDuplicate] = useState(null); useEffect(() => { localStorage.setItem(`${panelKey}_open`, Date.now()); setDuplicate(false); }, []); useEffect(() => { const onLocalStorageEvent = (e) => { if (e.key === `${panelKey}_open`) { setDuplicate(true); } }; window.addEventListener('storage', onLocalStorageEvent, false); return () => window.removeEventListener('storage', onLocalStorageEvent); }, []); if (duplicateTab === null) return null; if (duplicateTab) { return ( <Container> <h2>The panel {panel} is open in another window.</h2> <p>Click "Use Here" to use the panel in this window.</p> <ButtonGroup> <button onClick={() => window.location.reload()}>Reload to Use Here</button> </ButtonGroup> </Container> ); } return <>{children}</>; }; export default DuplicateTabChecker;
Предоставленный фрагмент кода представляет собой компонент React, который проверяет наличие дубликатов вкладок в одном и том же браузере. Давайте разберем функциональность и посмотрим, как она работает.
Проверка дубликатов вкладок
Компонент DuplicateTabChecker
обрабатывает логику проверки дубликатов вкладок. Вот как это работает:
- Компонент принимает три реквизита:
children
,panelKey
иpanel
. Свойствоchildren
представляет контент, который должен отображаться, если нет повторяющихся вкладок. СвойствоpanelKey
используется в качестве ключа в локальном хранилище для отслеживания состояния вкладки. Свойствоpanel
представляет собой имя проверяемой панели или компонента. - Внутри компонента мы определяем переменную состояния с именем
duplicateTab
, используя хукuseState
. Изначально установлено значениеnull
. - Мы используем хук
useEffect
с пустым массивом зависимостей, чтобы запускать код только один раз при монтировании компонента. Внутри этого эффекта мы устанавливаем текущую метку времени в локальном хранилище с помощью ключа${panelKey}_open
. Кроме того, мы устанавливаем состояниеduplicateTab
вfalse
, чтобы указать, что дубликаты вкладок не обнаружены. - Мы используем другой хук
useEffect
для прослушивания изменений в локальном хранилище. Когда происходит изменение, вызывается функцияonLocalStorageEvent
. Если ключ изменения соответствует${panelKey}_open
, это означает, что открыта другая вкладка с таким же ключом, и мы устанавливаем состояниеduplicateTab
наtrue
. - Мы добавляем прослушиватель событий для события
'storage'
и вызываем функциюonLocalStorageEvent
при возникновении события. Чтобы очистить прослушиватель событий, мы возвращаем функцию очистки в хукеuseEffect
, которая удаляет прослушиватель событий при размонтировании компонента. - Если состояние
duplicateTab
равноnull
, мы возвращаемnull
. Это полезно для предотвращения рендеринга любого контента до завершения проверки дубликатов вкладок. - Если состояние
duplicateTab
равноtrue
, мы визуализируем компонентContainer
с соответствующим сообщением, включая имяpanel
. Мы также визуализируем компонентButtonGroup
с кнопкой для перезагрузки текущей страницы и используем текущую вкладку вместо дубликата. - Если состояние
duplicateTab
равноfalse
, мы визуализируем реквизитchildren
, который представляет содержимое, которое будет отображаться, когда нет дубликатов вкладок.
Расширение на несколько браузеров и платформ
Хотя обсуждаемый нами код предназначен для работы в одном браузере, его можно расширить для работы в разных браузерах и платформах с помощью интеграции с сервером. Вот общий обзор подхода:
- Настройте сервер WebSocket, который может обрабатывать входящие подключения и сообщения от клиентов.
- Когда открывается новая вкладка, установите соединение WebSocket от клиентского приложения к серверу.
- После установления соединения WebSocket отправьте на сервер сообщение о том, что открыта новая вкладка. Включите соответствующую информацию, такую как идентификатор вкладки или любой другой идентификатор.
- На сервере прослушивайте входящие сообщения WebSocket. Когда получено сообщение, указывающее на новую вкладку, добавьте подключение WebSocket к определенной группе или каналу, связанному с «панелью».
- Как только соединение WebSocket будет добавлено в группу, отправьте сообщение всей группе, уведомляющее другие вкладки об открытии новой вкладки. Включите необходимые данные, такие как идентификатор вкладки или любой другой идентификатор.
- На стороне клиента каждая вкладка должна прослушивать сообщения WebSocket в группе «панель». Когда получено сообщение, указывающее на новую вкладку, обновите дублирующийся статус вкладки на
true
. - Обновите пользовательский интерфейс каждой вкладки, чтобы отразить повторяющийся статус. Например, отобразите сообщение или отключите определенные функции, чтобы предотвратить взаимодействие с повторяющимися вкладками.
Выполняя эти шаги и реализуя необходимые функции WebSocket, вы можете гарантировать, что при открытии новой вкладки она останется активной, а старые устаревшие вкладки не будут работать.
Интегрируя сервер в решение, вы можете синхронизировать информацию о вкладках в разных браузерах и платформах, обеспечивая единообразие работы и предотвращая дублирование вкладок независимо от используемого браузера или платформы.
Заключение
Обнаружение и обработка повторяющихся вкладок в одном и том же браузере может иметь решающее значение в определенных сценариях для обеспечения целостности данных и лучшего взаимодействия с пользователем. Фрагмент кода, который мы исследовали, предоставляет механизм для проверки дубликатов вкладок без интеграции с сервером. Преобразовав встроенные стили в стилизованные компоненты, мы улучшили удобство сопровождения и организацию кода. Кроме того, мы обсудили, как можно расширить код для работы в разных браузерах и платформах с помощью интеграции с сервером. Интегрируя сервер, вы можете обнаруживать дубликаты вкладок в нескольких браузерах и обеспечивать единообразие взаимодействия с пользователем.