Vue.js начиная с версии 3 предоставляет мощный инструмент для разработки компонентов — Composition API, который в сочетании с TypeScript обеспечивает строгую типизацию и улучшает читаемость кода. Composition API позволяет организовать логику компонентов в виде функций, что облегчает повторное использование кода и масштабирование приложений.
В основе Composition API лежит функция setup, которая
вызывается перед рендерингом компонента и возвращает объект, содержащий
реактивные данные, методы и вычисляемые свойства. В TypeScript важно
явно указывать типы для реактивных данных и функций.
Пример создания реактивного состояния:
import { ref, computed } from 'vue';
export default {
setup() {
const count = ref<number>(0); // реактивная переменная с типом number
const doubleCount = computed<number>(() => count.value * 2); // вычисляемое свойство с типом number
function increment(): void {
count.value++;
}
return { count, doubleCount, increment };
}
}
Ключевые моменты:
ref<T>() создаёт реактивное значение с явным
типом T.computed<T>() создаёт вычисляемое свойство с
указанным типом.setup можно типизировать так же, как
обычные TypeScript функции.Composition API позволяет строго типизировать props и events, что особенно важно в больших приложениях.
Props:
import { defineComponent } from 'vue';
export default defineComponent({
props: {
title: {
type: String,
required: true
},
count: {
type: Number,
default: 0
}
},
setup(props) {
const titleLength: number = props.title.length;
return { titleLength };
}
});
Для сложных структур данных рекомендуется использовать интерфейсы:
interface User {
id: number;
name: string;
}
export default defineComponent({
props: {
user: {
type: Object as () => User,
required: true
}
},
setup(props) {
const userName: string = props.user.name;
return { userName };
}
});
Emits:
События можно типизировать с помощью defineEmits:
const emit = defineEmits<{
(e: 'update', value: number): void;
(e: 'delete', id: string): void;
}>();
function updateValue(newValue: number) {
emit('update', newValue);
}
Типизация emit позволяет избежать ошибок при вызове
событий и обеспечивает автодополнение в редакторе.
ref vs reactiveВ Composition API есть два способа создания реактивного состояния:
ref и reactive.
ref создаёт примитив или объект, к которому можно
обращаться через .value:
const message = ref<string>('Hello');
message.value = 'Hi';
reactive создаёт реактивный объект, где доступ к свойствам осуществляется напрямую:
import { reactive } from 'vue';
interface State {
count: number;
text: string;
}
const state = reactive<State>({
count: 0,
text: 'Hello'
});
state.count++;
state.text = 'Hi';
Важно помнить: для примитивов лучше использовать ref,
для объектов и массивов — reactive.
Computed свойства позволяют создавать производные значения на основе реактивного состояния:
const fullName = computed<string>(() => `${state.firstName} ${state.lastName}`);
Watch используется для реакции на изменения состояния:
import { watch } from 'vue';
watch(() => state.count, (newValue, oldValue) => {
console.log(`Count changed from ${oldValue} to ${newValue}`);
});
Типизация обеспечивает строгий контроль типов, особенно при сложных структурах состояния.
При интеграции с Vue Router и Vuex TypeScript позволяет типизировать параметры маршрутов и состояния хранилища:
import { useRoute } from 'vue-router';
import { useStore } from 'vuex';
const route = useRoute();
const store = useStore<{ count: number }>();
const id: string = route.params.id as string;
const currentCount: number = store.state.count;
Такой подход предотвращает ошибки при обращении к параметрам маршрута или состоянию хранилища.
ref для примитивов и reactive
для объектов.setup, чтобы
сохранить автодополнение и строгую проверку типов.Composition API с TypeScript делает код более предсказуемым, сокращает количество ошибок во время разработки и улучшает поддержку крупных проектов Vue.js.