Представляем вам Vue 3.3

от автора

Эта статья — перевод оригинальной статьи «Announcing Vue 3.3«

Также я веду телеграм канал “Frontend по-флотски”, где рассказываю про интересные вещи из мира разработки интерфейсов.

Вступление

Сегодня мы рады объявить о релизе Vue 3.3 «Rurouni Kenshin»!

Этот выпуск сосредоточен на улучшении опыта разработки — в частности, на использовании SFC <script setup> с TypeScript. Вместе с релизом 1.6 Vue Language Tools (ранее известного как Volar) мы решили многие давние проблемы при использовании Vue с TypeScript.

В этом посте представлен обзор основных возможностей версии 3.3. Для получения полного списка изменений, пожалуйста, ознакомьтесь с полным журналом изменений на GitHub.

<script setup> + Улучшения TypeScript DX

Поддержка импортированных и сложных типов в макросах

Ранее типы, используемые в параметре типа в defineProps и defineEmits, были ограничены локальными типами и поддерживали только литералы типов и интерфейсы. Это связано с тем, что Vue должен иметь возможность анализировать свойства интерфейса props для генерации соответствующих опций во время выполнения.

Теперь это ограничение устранено в версии 3.3. Компилятор теперь может разрешать импортированные типы и поддерживает ограниченный набор сложных типов:

<script setup lang="ts"> import type { Props } from './foo'  // imported + intersection type defineProps<Props & { extraProp?: string }>() </script>

Обратите внимание, что поддержка сложных типов основана на AST и поэтому не является на 100% полной. Некоторые сложные типы, требующие фактического анализа типа, например, условные типы, не поддерживаются. Вы можете использовать условные типы для определения типа отдельного параметра, но не всего объекта параметров.

Подробнее: PR#8083

Обобщенные компоненты

Компоненты, использующие <script setup>, теперь могут принимать параметры обобщенных типов через атрибут generic:

<script setup lang="ts" generic="T"> defineProps<{   items: T[]   selected: T }>() </script>

Значение generic работает точно так же, как список параметров между <…> в TypeScript. Например, можно использовать множественные параметры, ограничения extends, типы по умолчанию и ссылочные импортированные типы:

<script setup lang="ts" generic="T extends string | number, U extends Item"> import type { Item } from './types' defineProps<{   id: T   list: U[] }>() </script>

Ранее эта функция требовала явного согласия пользователя, но теперь она включена по умолчанию в последней версии volar / vue-tsc.

Более эргономичный defineEmits

Ранее параметр типа для defineEmits поддерживал только синтаксис сигнатуры вызова:

// Раньше const emit = defineEmits<{   (e: 'foo', id: number): void   (e: 'bar', name: string, ...rest: any[]): void }>()

Тип совпадает с типом возврата для emit, но он немного многословен и неудобен в написании. В версии 3.3 представлен более эргономичный способ объявления эмитов с помощью типов:

// Теперь const emit = defineEmits<{   foo: [id: number]   bar: [name: string, ...rest: any[]] }>()

В литерале типа ключом является имя события, а значением — тип массива, определяющий дополнительные аргументы. Хотя это не обязательно, вы можете использовать помеченные элементы кортежа для ясности, как в примере выше.

Синтаксис сигнатуры вызова по-прежнему поддерживается.

Типизированные слоты с defineSlots

Новый макрос defineSlots можно использовать для объявления ожидаемых слотов и соответствующих им параметров:

<script setup lang="ts"> defineSlots<{   default?: (props: { msg: string }) => any   item?: (props: { id: number }) => any }>() </script>

defineSlots() принимает только параметр типа и никаких рантайм аргументов. Параметр типа должен быть литералом типа, где ключ свойства — имя слота, а значение — функция слота. Первым аргументом функции является проп, который слот ожидает получить, и его тип будет использоваться для пропсов слота в шаблоне. Возвращаемое значение defineSlots — это тот же объект слота, который возвращается из useSlots.

Некоторые текущие ограничения:

  • Проверка требуемых слотов пока не реализована в volar / vue-tsc.

  • Тип возврата функции слота в настоящее время игнорируется и может быть any, но мы можем использовать его для проверки содержимого слота в будущем.

Существует также соответствующая опция слотов для использования defineComponent. Оба API не имеют последствий во время выполнения и служат исключительно в качестве подсказок типов для IDE и vue-tsc.

Подробнее: PR#7982

Экспериментальные возможности

Реактивные пропсы Деструктура

Ранее являвшаяся частью исчезнувшего Reactivity Transform, деструктура реактивных пропсов была выделена в отдельную функцию.

Эта функция позволяет деструктурированным пропсам сохранять реактивность и обеспечивает более эргономичный способ объявления значений пропсов по умолчанию:

<script setup> import { watchEffect } from 'vue'  const { msg = 'hello' } = defineProps(['msg'])  watchEffect(() => {   // accessing `msg` in watchers and computed getters   // tracks it as a dependency, just like accessing `props.msg`   console.log(`msg is: ${msg}`) }) </script>  <template>{{ msg }}</template>

Эта функция является экспериментальной и требует явного согласия.

Подробнее: RFC#502

defineModel

Ранее, чтобы компонент поддерживал двустороннее связывание с v-model, он должен был (1) объявить пропс и (2) вызвать соответствующее событие update:propName, когда он намеревался обновить пропс:

<!-- ДО --> <script setup> const props = defineProps(['modelValue']) const emit = defineEmits(['update:modelValue']) console.log(props.modelValue)  function onInput(e) {   emit('update:modelValue', e.target.value) } </script>  <template>   <input :value="modelValue" @input="onInput" /> </template>

3.3 упрощает использование с помощью нового макроса defineModel. Макрос автоматически регистрирует проп и возвращает ref, который может быть непосредственно изменен:

<!-- ПОСЛЕ --> <script setup> const modelValue = defineModel() console.log(modelValue.value) </script>  <template>   <input v-model="modelValue" /> </template>

Эта функция является экспериментальной и требует явного согласия.

Подробнее: RFC#503

Другие примечательные возможности

defineOptions

Новый макрос defineOptions позволяет объявлять опции компонента непосредственно в <script setup>, не требуя отдельного блока <script>:

<script setup> defineOptions({ inheritAttrs: false }) </script>

Улучшенная поддержка геттеров с помощью toRef и toValue

toRef был улучшен для поддержки нормализации значений / геттеров / существующих refs внутри refs:

// Равносильно ref(1) toRef(1) // создает readonly ref, который вызывает getter при доступе к .value toRef(() => props.foo) // Возвращает существующий refs как есть toRef(existingRef)

Вызов toRef с геттером аналогичен computed, но может быть более эффективным, если геттер просто выполняет доступ к свойству без дорогостоящих вычислений.

Новый метод toValue обеспечивает обратное, нормализуя значения/геттеры/рефы в значения:

toValue(1) //       --> 1 toValue(ref(1)) //  --> 1 toValue(() => 1) // --> 1

toValue можно использовать в составных элементах вместо unref, чтобы ваш составной элемент мог принимать геттеры в качестве реактивных источников данных:

// до: выделение ненужных промежуточных ссылок useFeature(computed(() => props.foo)) useFeature(toRef(props, 'foo'))  // после: более эффективно и лаконично useFeature(() => props.foo)

Отношения между toRef и toValue аналогичны отношениям между ref и unref, основное отличие заключается в особой обработке функций getter.

Подробнее: PR#7997

Поддержка импорта исходного кода JSX

В настоящее время типы Vue автоматически регистрируют глобальную JSX-типизацию. Это может привести к конфликту при использовании вместе с другими библиотеками, которым необходим вывод типов JSX, в частности React.

Начиная с версии 3.3, Vue поддерживает указание пространства имен JSX через опцию jsxImportSource в TypeScript. Это позволяет пользователям выбирать глобальный или индивидуальный выбор файла в зависимости от их сценария использования.

Для обратной совместимости в версии 3.3 пространство имен JSX по-прежнему регистрируется глобально. Мы планируем убрать глобальную регистрацию по умолчанию в версии 3.4. Если вы используете TSX с Vue, вам следует добавить явный jsxImportSource в tsconfig.json после обновления до 3.3, чтобы избежать поломки в 3.4.

Улучшение инфраструктуры поддержки

Этот релиз основан на многочисленных улучшениях инфраструктуры поддержки, которые позволяют нам двигаться быстрее и увереннее:

  • Сборка в 10 раз быстрее благодаря отделению проверки типов от сборки rollup и переходу от rollup-plugin-typescript2 к rollup-plugin-esbuild.

  • Более быстрые тесты благодаря переходу от Jest к Vitest.

  • Более быстрая генерация типов за счет перехода от @microsoft/api-extractor к rollup-plugin-dts.

  • Комплексные регрессионные тесты с помощью ecosystem-ci — отлавливают регрессии в основных зависимых компонентах экосистемы до выпуска релизов!

Как и планировалось, в 2023 году мы намерены начать выпускать более мелкие и частые релизы функций. Следите за новостями!


ссылка на оригинал статьи https://habr.com/ru/articles/735086/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *