Эта статья — перевод оригинальной статьи «Announcing Vue 3.5».
Также я веду телеграм канал «Frontend по‑флотски», где рассказываю про интересные вещи из мира разработки интерфейсов.
Вступление
Сегодня мы рады сообщить о выходе Vue 3.5 «Tengen Toppa Gurren Lagann»!
Этот минорный релиз не содержит кардинальных изменений и включает в себя как внутренние улучшения, так и новые полезные функции. Мы расскажем о некоторых основных моментах в этом блоге — полный список изменений и новых возможностей можно найти в полном журнале изменений на GitHub.
Оптимизация системы реактивности
В версии 3.5 система реактивности Vue подверглась очередному масштабному рефакторингу, который позволил добиться более высокой производительности и значительно улучшить использование памяти (-56 %) без каких-либо изменений в поведении. Рефакторинг также решает проблемы с устаревшими computed
и памятью, вызванные зависанием computed
во время SSR.
Кроме того, в 3.5 оптимизировано отслеживание реактивности для больших, глубоко реактивных массивов, что в некоторых случаях ускоряет такие операции до 10 раз.
Подробности: PR#10397, PR#9511
Реактивная деструктуризация props
Реактиваная деструктуризация props была стабилизирована в 3.5. Теперь эта функция включена по умолчанию, и переменные, деструктурированные в результате вызова defineProps в <script setup>, теперь являются реактивными. Примечательно, что эта функция значительно упрощает объявление props со значениями по умолчанию, используя нативный JavaScript синтаксис значений по умолчанию:
До:
const props = withDefaults( defineProps<{ count?: number msg?: string }>(), { count: 0, msg: 'hello' } )
После:
const { count = 0, msg = 'hello' } = defineProps<{ count?: number message?: string }>()
Доступ к деструктурированной переменной, например count, автоматически компилируется компилятором в props.count, поэтому они отслеживаются при доступе. Как и в случае с props.count, просмотр деструктурированной переменной prop или передача ее в composable функцию с сохранением реактивности требует обернуть ее в геттер:
watch(count /* ... */) // ^ приводит к ошибке compile-time error watch(() => count /* ... */) // ^ обернув в геттер, работает как ожидалось // composable должны нормализовать входные данные с помощью `toValue()` useDynamicCount(() => count)
Для тех, кто предпочитает лучше отличать деструктурированные реквизиты от обычных переменных, в @vuelanguage-tools 2.1
появилась опциональная настройка, позволяющая включать для них подсказки:
Подробности:
См. документацию по использованию и предостережения. См. RFC#502 для истории и обоснования дизайна этой функции.
Улучшения SSR
В версии 3.5 реализовано несколько давно ожидаемых улучшений в рендеринге на стороне сервера (SSR).
Ленивая гидратация
Теперь асинхронные компоненты могут контролировать время гидратации, указывая стратегию с помощью опции hydrate
в API defineAsyncComponent()
. Например, чтобы компонент гидратировался только тогда, когда он становится видимым:
import { defineAsyncComponent, hydrateOnVisible } from 'vue' const AsyncComp = defineAsyncComponent({ loader: () => import('./Comp.vue'), hydrate: hydrateOnVisible() })
Основной API намеренно более низкого уровня, и команда Nuxt уже создает синтаксический сахар более высокого уровня на основе этой функции.
Подробности: PR#11458
useId()
useId()
— это API, который можно использовать для генерации уникальных идентификаторов для каждого приложения, которые гарантированно будут стабильными при рендеринге на сервере и клиенте. Они могут использоваться для генерации идентификаторов элементов форм и атрибутов доступности, а также могут применяться в SSR-приложениях, не приводя к несоответствию гидратации:
<script setup> import { useId } from 'vue' const id = useId() </script> <template> <form> <label :for="id">Name:</label> <input :id="id" type="text" /> </form> </template>
Подробнее: PR#11404
data-allow-mismatch
В случаях, когда клиентское значение неизбежно отличается от своего серверного аналога (например, даты), мы теперь можем подавлять возникающие предупреждения о несоответствии гидратация с помощью атрибутов data-allow-mismatch
:
<span data-allow-mismatch>{{ data.toLocaleString() }}</span>
Вы также можете ограничить допустимые типы несоответствий, указав значение атрибута, где возможными значениями являются text
, children
, class
, style
иattribute
.
Улучшения пользовательских элементов
В версии 3.5 исправлено множество давних проблем, связанных с API defineCustomElement()
, и добавлен ряд новых возможностей для создания пользовательских элементов с помощью Vue:
-
Поддержка конфигураций приложений для пользовательских элементов с помощью опции
configureApp
. -
Добавьте
useHost()
,useShadowRoot()
иthis.$host
для доступа к элементу host и shadow root пользовательского элемента. -
Поддержка установки пользовательских элементов без Shadow DOM путем передачи
shadowRoot: false
. -
Поддержка предоставления опции nonce, которая будет прикрепляться к тегам
<style>
, вводимым пользовательскими элементами.
Эти новые опции, предназначенные только для пользовательских элементов, могут быть переданы в defineCustomElement
через второй аргумент:
import MyElement from './MyElement.ce.vue' defineCustomElements(MyElement, { shadowRoot: false, nonce: 'xxx', configureApp(app) { app.config.errorHandler = ... } })
Другие примечательные особенности
useTemplateRef()
В версии 3.5 появился новый способ получения ссылок на шаблоны с помощью API useTemplateRef()
:
<script setup> import { useTemplateRef } from 'vue' const inputRef = useTemplateRef('input') </script> <template> <input ref="input"> </template>
До версии 3.5 мы рекомендовали использовать обычные ссылки с именами переменных, совпадающими со статическими атрибутами ссылок. Старый подход требовал, чтобы атрибуты ссылок были анализируемы компилятором, и поэтому был ограничен статическими атрибутами ссылок. В отличие от этого, useTemplateRef()
сопоставляет рефссылки по идентификаторам строк времени выполнения, поэтому поддерживает динамическое привязывание рефссылки к изменяющимся идентификаторам.
В @vue/language-tools 2.1
также реализована специальная поддержка нового синтаксиса, поэтому при использовании useTemplateRef()
вы получите автодополнение и предупреждения, основанные на наличии атрибутов ref в вашем шаблоне:
Deferred Teleport
Известное ограничение встроенного компонента <Teleport>
заключается в том, что его целевой элемент должен существовать в момент установки компонента телепортации. Это не позволяло пользователям телепортировать содержимое в другие элементы, отрисованные Vue после телепортации.
В 3.5 мы добавили свойство defer
для <Teleport>
, которое монтирует его после текущего цикла рендеринга, так что теперь это будет работать:
<Teleport defer target="#container">...</Teleport> <div id="container"></div>
Это поведение требует prop defer
, потому что поведение по умолчанию должно быть обратно совместимым.
Подробнее: PR#11387
onWatcherCleanup()
В версии 3.5 появился глобально импортируемый API, onWatcherCleanup(), для регистрации обратных вызовов очистки в наблюдателях:
import { watch, onWatcherCleanup } from 'vue' watch(id, (newId) => { const controller = new AbortController() fetch(`/api/${newId}`, { signal: controller.signal }).then(() => { // callback logic }) onWatcherCleanup(() => { // abort stale request controller.abort() }) })
Связано: новый раздел документации по очистке побочных эффектов
ссылка на оригинал статьи https://habr.com/ru/articles/840806/
Добавить комментарий