Fragment¶
<Fragment>, часто используемый через синтаксис <>...</>, позволяет группировать элементы без узла-обертки.
1 2 3 4 | |
Описание¶
<Fragment>¶
Оберните элементы в <Fragment>, чтобы сгруппировать их вместе в ситуациях, когда вам нужен один элемент. Группировка элементов в Fragment не влияет на результирующий DOM; он такой же, как если бы элементы не были сгруппированы. Пустой JSX-тег <></> в большинстве случаев является сокращением для <Fragment></Fragment>.
Параметры¶
- опционально
key: Фрагменты, объявленные с явным синтаксисом<Fragment>, могут иметь ключи.
Предупреждения¶
-
Если вы хотите передать
keyфрагменту, вы не можете использовать синтаксис<>...</>. Вы должны явно импортироватьFragmentиз'react'и передать<Fragment key={yourKey}>...</Fragment>. -
React не сбрасывает состояние, когда вы переходите от рендеринга
<><Child /></>к[<Child />]или обратно, или когда вы переходите от рендеринга<><Child /></>к<Child />и обратно. Это работает только на одном уровне в глубину: например, переход от<><><Child /></></>к<Child />сбрасывает состояние. Точную семантику можно посмотреть здесь.
FragmentInstance¶
Когда во фрагмент передают ref, React даёт объект FragmentInstance. У него есть методы для работы с DOM-потомками первого уровня, которые обёрнуты фрагментом.
addEventListenerиremoveEventListenerуправляют слушателями событий на всех DOM-потомках первого уровня.dispatchEventотправляет событие на фрагменте, и оно может всплыть к родительскому DOM-узлу.focus,focusLastиblurуправляют фокусом по всем вложенным потомкам в порядке обхода в глубину.observeUsingиunobserveUsingподключают и отключают экземплярыIntersectionObserverилиResizeObserver.getClientRectsвозвращает ограничивающие прямоугольники всех DOM-потомков первого уровня.getRootNodeвозвращает корневой узел родителя фрагмента.compareDocumentPositionсравнивает позицию фрагмента с другим узлом.scrollIntoViewпрокручивает потомков фрагмента в область видимости.
addEventListener(type, listener, options?)¶
Добавляет слушатель события ко всем DOM-потомкам фрагмента первого уровня.
1 | |
Параметры¶
type: строка с типом события (например,'click','focus').listener: функция-обработчик события.- необязательно
options: объект параметров или булево значение для захвата, как в DOM APIaddEventListener.
Возвращаемое значение¶
addEventListener ничего не возвращает (undefined).
removeEventListener(type, listener, options?)¶
Удаляет слушатель события со всех DOM-потомков фрагмента первого уровня.
1 | |
Параметры¶
type: строка с типом события.listener: функция-обработчик, которую нужно удалить.- необязательно
options: объект параметров или булево значение, как в DOM APIremoveEventListener.
Возвращаемое значение¶
removeEventListener ничего не возвращает (undefined).
dispatchEvent(event)¶
Отправляет событие на фрагменте. Вызываются добавленные слушатели, и событие может всплыть к родительскому DOM-узлу фрагмента.
1 | |
Параметры¶
event: объектEvent, который нужно отправить. Еслиbubblesравенtrue, событие всплывает к родительскому DOM-узлу фрагмента.
Возвращаемое значение¶
true, если событие не отменено, и false, если вызван preventDefault().
focus(options?)¶
Переводит фокус на первый фокусируемый DOM-узел внутри фрагмента. В отличие от element.focus() на DOM-элементе, этот метод ищет всех вложенных потомков в глубину, пока не найдёт фокусируемый элемент, а не только сам элемент или его прямых потомков.
1 | |
Параметры¶
- необязательно
options: объектFocusOptions(например,{ preventScroll: true }).
Возвращаемое значение¶
focus ничего не возвращает (undefined).
focusLast(options?)¶
Переводит фокус на последний фокусируемый DOM-узел внутри фрагмента. Ищет вложенных потомков в глубину, а затем идёт в обратном порядке.
1 | |
Параметры¶
- необязательно
options: объектFocusOptions.
Возвращаемое значение¶
focusLast ничего не возвращает (undefined).
blur()¶
Снимает фокус с активного элемента, если он находится внутри фрагмента. Если document.activeElement не внутри фрагмента, blur ничего не делает.
1 | |
Возвращаемое значение¶
blur ничего не возвращает (undefined).
observeUsing(observer)¶
Начинает наблюдение за всеми DOM-потомками фрагмента первого уровня переданным наблюдателем.
1 2 | |
Параметры¶
observer: экземплярIntersectionObserverилиResizeObserver.
Возвращаемое значение¶
observeUsing ничего не возвращает (undefined).
unobserveUsing(observer)¶
Прекращает наблюдение за DOM-потомками фрагмента указанным наблюдателем.
1 | |
Параметры¶
observer: тот же экземплярIntersectionObserverилиResizeObserver, который раньше передали вobserveUsing.
Возвращаемое значение¶
unobserveUsing ничего не возвращает (undefined).
getClientRects()¶
Возвращает плоский массив объектов DOMRect с ограничивающими прямоугольниками всех DOM-потомков первого уровня.
1 | |
Возвращаемое значение¶
Array<DOMRect> с ограничивающими прямоугольниками всех потомков.
getRootNode(options?)¶
Возвращает корневой узел, в котором находится родительский DOM-узел фрагмента, как Node.getRootNode().
1 | |
Параметры¶
- необязательно
options: объект с булевым свойствомcomposed, как в DOM APIgetRootNode.
Возвращаемое значение¶
Document, ShadowRoot или сам FragmentInstance, если родительского DOM-узла нет.
compareDocumentPosition(otherNode)¶
Сравнивает позицию фрагмента в документе с другим узлом и возвращает битовую маску, как Node.compareDocumentPosition().
1 | |
Параметры¶
otherNode: DOM-узел, с которым нужно сравнить.
Возвращаемое значение¶
Битовая маска флагов позиции. Пустые фрагменты и фрагменты, чьи потомки отрендерены через портал, включают в результат Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC.
scrollIntoView(alignToTop?)¶
Прокручивает потомков фрагмента в область видимости. Если alignToTop равен true или опущен, прокрутка выравнивает первого потомка по верху прокручиваемого предка. Если alignToTop равен false, прокрутка выравнивает последнего потомка по низу.
1 | |
Параметры¶
- необязательно
alignToTop: булево значение. Еслиtrue(по умолчанию), первый потомок прокручивается к верху прокручиваемой области. Еслиfalse, последний потомок прокручивается к низу. В отличие отElement.scrollIntoView(), этот метод не принимает объектScrollIntoViewOptions.
Возвращаемое значение¶
scrollIntoView ничего не возвращает (undefined).
Предупреждения¶
scrollIntoViewне принимает объект параметров. Если его передать, будет ошибка. Используйте булево значениеalignToTop.- Если у фрагмента нет потомков,
scrollIntoViewв качестве фолбэка прокручивает в область видимости ближайшего соседа или родителя.
Предупреждения FragmentInstance¶
- Методы, которые работают с потомками (
addEventListener,observeUsing,getClientRects), действуют на хост-потомков (DOM) первого уровня фрагмента. Они не нацелены напрямую на потомков, вложенных в другой DOM-элемент. focusиfocusLastищут фокусируемые элементы среди вложенных потомков в глубину, в отличие от методов событий и наблюдателей, которые затрагивают только хост-потомков первого уровня.observeUsingне работает с текстовыми узлами. В разработке React пишет предупреждение, если фрагмент содержит только текстовых потомков.- React не вешает слушатели, добавленные через
addEventListener, на скрытые деревья<Activity>. Когда границаActivityпереключается со скрытой на видимую, слушатели применяются автоматически. - Каждый DOM-потомок первого уровня фрагмента с
refполучает свойствоreactFragments—Set<FragmentInstance>со всеми экземплярами фрагмента, которым принадлежит элемент. Это позволяет кэшировать общий наблюдатель для нескольких фрагментов.
Использование¶
Возвращение нескольких элементов¶
Используйте Fragment или эквивалентный синтаксис <>...</> для группировки нескольких элементов вместе. С его помощью вы можете поместить несколько элементов в любое место, где может находиться один элемент. Например, компонент может вернуть только один элемент, но с помощью фрагмента вы можете сгруппировать несколько элементов вместе и затем вернуть их как группу:
1 2 3 4 5 6 7 8 | |
Фрагменты полезны тем, что группировка элементов с помощью фрагмента не влияет на макет или стили, в отличие от того, если бы вы обернули элементы в другой контейнер, например, DOM-элемент. Если вы посмотрите этот пример с помощью инструментов браузера, вы увидите, что все узлы DOM <h1> и <article> выглядят как родные братья и сестры без оберток вокруг них:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | |
Как написать фрагмент без специального синтаксиса?
Приведенный выше пример эквивалентен импорту Fragment из React:
1 2 3 4 5 6 7 8 9 10 | |
Обычно это не нужно, если только вам не нужно передать ключ вашему фрагменту.
Присвоение переменной нескольких элементов¶
Как и любой другой элемент, вы можете присваивать элементы Fragment переменным, передавать их в качестве пропсов и так далее:
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Группировка элементов с помощью текста¶
Вы можете использовать Fragment для группировки текста вместе с компонентами:
1 2 3 4 5 6 7 8 9 10 | |
Рендеринг списка фрагментов¶
Вот ситуация, когда вам нужно написать Fragment явно вместо использования синтаксиса <></>. Когда вы рендерите несколько элементов в цикле, вам нужно назначить key каждому элементу. Если элементы в цикле являются фрагментами, то для указания атрибута key необходимо использовать обычный синтаксис JSX-элементов:
1 2 3 4 5 6 7 8 | |
Вы можете просмотреть DOM, чтобы убедиться, что вокруг дочерних элементов фрагмента нет элементов-оберток:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | |
Слушатели событий без элемента-обёртки¶
Рефы фрагмента позволяют добавить слушатели событий к группе элементов, не добавляя DOM-узел-обёртку. Чтобы подключить и очистить слушатели, используйте ref-колбэк:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | |
1 2 3 4 5 6 7 | |
Вызов addEventListener вешает слушатель на каждого DOM-потомка фрагмента первого уровня. Когда потомков динамически добавляют или удаляют, FragmentInstance сам добавляет или снимает слушатель.
Каких потомков затрагивает реф фрагмента?
FragmentInstance нацелен на хост-потомков (DOM) первого уровня фрагмента. Рассмотрим такое дерево:
1 2 3 4 5 6 7 8 9 | |
Wrapper — это компонент React, поэтому FragmentInstance смотрит сквозь него в поисках DOM-узлов. Целевые потомки — A, B и D. C не входит в них, потому что вложен в DOM-элемент B.
Методы вроде addEventListener, observeUsing и getClientRects работают с этими DOM-потомками первого уровня. focus и focusLast устроены иначе: они ищут всех вложенных потомков в глубину, чтобы найти фокусируемые элементы.
Фокус на группе элементов¶
Рефы фрагмента дают методы focus, focusLast и blur, которые работают со всеми DOM-узлами внутри фрагмента:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
1 2 3 4 5 6 7 8 9 | |
1 2 3 4 5 6 7 | |
Вызов focus() фокусирует поле street, хотя оно вложено в <fieldset> и <label>. focus() ищет в глубину всех вложенных потомков, а не только прямых потомков фрагмента. focusLast() делает то же самое в обратном порядке, а blur() снимает фокус, если сейчас сфокусирован элемент внутри фрагмента.
Прокрутка группы элементов в область видимости¶
scrollIntoView прокручивает потомков фрагмента в область видимости без элемента-обёртки. Передайте true (или опустите аргумент), чтобы прокрутить первого потомка к верху. Передайте false, чтобы прокрутить последнего потомка к низу:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
1 2 3 4 5 6 7 | |
Наблюдение за видимостью без элемента-обёртки¶
observeUsing подключает IntersectionObserver ко всем DOM-потомкам фрагмента первого уровня. Так можно следить за видимостью, не заставляя дочерние компоненты отдавать ref и не добавляя элемент-обёртку:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
1 2 3 | |
1 2 3 4 5 6 7 | |
Кэширование общего IntersectionObserver¶
Частая оптимизация для страниц со множеством наблюдателей — один IntersectionObserver на конфигурацию и маршрутизация его записей в нужные колбэки по тому, какой элемент пересёкся. Рефы фрагмента поддерживают тот же приём через свойство reactFragments.
У каждого DOM-потомка первого уровня фрагмента с ref есть свойство reactFragments: Set объектов FragmentInstance, которые содержат этот элемент. Когда срабатывает общий наблюдатель, по этому свойству можно найти, какому FragmentInstance принадлежит пересекающийся элемент, и вызвать нужные колбэки.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | |
1 2 3 | |
1 2 3 4 5 6 7 | |
Несколько компонентов ObservedGroup с одинаковыми параметрами переиспользуют один IntersectionObserver. Когда любая из секций прокручивается в область видимости, общий наблюдатель срабатывает и через reactFragments направляет запись в нужный колбэк.
Источник — https://react.dev/reference/react/Fragment