Ques/Help/Req Обзор Vue 3.3. Что изменилось и при чём тут TypeScript

XakeR

Member
Регистрация
13.05.2006
Сообщения
1 912
Реакции
0
Баллы
16
Местоположение
Ukraine
Команда Vue сообщила о выпуске версии 3.3 — «Rurouni Kenshin».

В новой версии разработчики постарались улучшить опыт разработки. К примеру, было улучшено взаимодействие с SFC <script setup> на TypeScript.

Также были решены многие давние проблемы с использованием Vue и TypeScript.

Основные изменения​


Обновления зависимостей

Чтобы обновиться до Vue 3.3, нужно также обновить зависимости:

  1. volar / vue-tsc@^1.6.4;
  2. vite@^4.3.5;
  3. @vitejs/plugin-vue@^4.2.0;
  4. vue-loader@^17.1.0 (если используется webpack или vue-cli).

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

До версии 3.3 типы в defineProps и defineEmits могли быть только локальными типами и поддерживали только литералы типов.

Java разработчик (проект по созданию системы класса IDM) АО «Гринатом», , можно удалённо, По итогам собеседования tproger.ru Вакансии на tproger.ru

Так было потому, что Vue нужно было анализировать свойства props для генерации опций во время выполнения кода.

Теперь, в версии 3.3, компилятор разрешает использовать импортированные и комплексные, сложные типы:

<script setup lang=»ts»> import type { Props } from ‘./foo’ // imported + intersection type defineProps<Props undefined { extraProp?: string }>() </script>

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

Вы можете использовать условные типы для одного параметра, но не для объекта параметров.

Универсальные компоненты

Компоненты <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 поддерживал только синтаксис сигнатуры вызова:

// BEFORE const emit = defineEmits<{ (e: ‘foo’, id: number): void (e: ‘bar’, name: string, …rest: any[]): void }>()

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

// AFTER 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() принимает только параметр типа, но не принимает аргументы рантайма.

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

Первый аргумент функции — props, тип которых будет использоваться для пропсов слота в шаблоне.

Значение defineSlots — это тот же объект слотов, который возвращается из useSlots.

Текущие ограничения

  1. Проверка слотов еще не реализована в volar/vue-tsc.
  2. Тип возврата функции слота может быть любым, но в будущем он может использоваться для проверки содержимого слота.

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

Экспериментальные функции​


Деструктуризация реактивных пропсов

Деструктура реактивных пропсов ранее была частью преобразования реактивности, которое теперь удалено. Сейчас она выделена в отдельную функцию.

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

<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>

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

defineModel

Ранее, чтобы компонент поддерживал двустороннюю привязку к v-модели, ему необходимо было объявить свойство и создать событие update:propName, чтобы свойство обновлялось:

<!— BEFORE —> <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. Макрос автоматически объявляет свойство и возвращает ссылку:

<!— AFTER —> <script setup> const modelValue = defineModel() console.log(modelValue.value) </script> <template> <input v-model=»modelValue» /> </template>

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

Другие примечательные особенности​


defineOptions

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

<script setup> defineOptions({ inheritAttrs: false }) </script> Лучшая поддержка Getter с toRef и toValue

toRef улучшен для поддержки нормализации значений, геттеров и refs:

// equivalent to ref(1) toRef(1) // creates a readonly ref that calls the getter on .value access toRef(() => props.foo) // returns existing refs as-is toRef(existingRef)

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

Новый служебный метод toValue делает всё наоборот, нормализуя всё в значения:

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

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

// before: allocating unnecessary intermediate refs useFeature(computed(() => props.foo)) useFeature(toRef(props, ‘foo’)) // after: more efficient and succinct useFeature(() => props.foo)

Разница между toRef и toValue такая же, как между ref и unref. Разница только в обработке функций-получателей.

Импорт исходного кода JSX

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

Начиная с версии 3.3, Vue поддерживает указание типизаций JSX с помощью параметра TypeScript jsxImportSource.

Улучшение инфраструктуры обслуживания​


Вот, что улучшили в выпуске 3.3:

  1. Сборки стали в 10 раз быстрее благодаря отделению проверки типов от сводной сборки и переходу от rollup-plugin-typescript2 к rollup-plugin-esbuild.
  2. Ускорились тесты за счет перехода с Jest на Vitest.
  3. Ускорилось создание типов за счет перехода от @Microsoft/api-extractor к rollup-plugin-dts.
  4. Комплексные регрессионные тесты с помощью ecosystem-ci позволяют выявлять регрессии в основных зависимостях перед выпуском.

***

В этом посте рассмотрели основные изменения в версии 3.3. Ознакомиться с полным списком обновлений можно на GitHub.
 
198 175Темы
635 146Сообщения
3 618 415Пользователи
еу4уууеууеНовый пользователь
Верх