← Назад к вопросам
Как задать значение по умолчанию у define props?
2.0 Middle🔥 181 комментариев
#Vue.js
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Значения по умолчанию в defineProps (Vue)
Хочу сразу уточнить, что я в основном работаю с React, но в Vue 3 с Composition API значения по умолчанию для props задаются несколькими способами. Вот полный гайд.
Способ 1: Использовать функцию withDefaults (рекомендуется)
Это самый современный и удобный способ в Vue 3.3+:
// MyComponent.vue
<script setup lang="ts">
interface Props {
title: string;
count?: number;
disabled?: boolean;
items?: string[];
mode?: 'dark' | 'light';
}
const props = withDefaults(defineProps<Props>(), {
count: 0,
disabled: false,
items: () => [], // для массивов и объектов нужна функция
mode: 'light'
});
</script>
<template>
<div>
<h1>{{ title }}</h1>
<p>Count: {{ count }}</p>
<p>Mode: {{ mode }}</p>
<p v-if="disabled">Component is disabled</p>
<ul>
<li v-for="item in items" :key="item">{{ item }}</li>
</ul>
</div>
</template>
Способ 2: Через объект в defineProps
Это классический способ для JavaScript:
// MyComponent.vue
<script setup>
const props = defineProps({
title: {
type: String,
required: true
},
count: {
type: Number,
default: 0
},
disabled: {
type: Boolean,
default: false
},
items: {
type: Array,
default: () => [] // функция для изменяемых значений
},
mode: {
type: String,
default: 'light',
validator: (value) => ['dark', 'light'].includes(value)
}
});
</script>
<template>
<div>
<h1>{{ title }}</h1>
<p>Count: {{ count }}</p>
<p>Mode: {{ mode }}</p>
</div>
</template>
Способ 3: С валидацией
<script setup lang="ts">
interface Props {
status?: 'pending' | 'success' | 'error';
timeout?: number;
callback?: (data: any) => void;
}
const props = withDefaults(defineProps<Props>(), {
status: 'pending',
timeout: 3000
});
// Валидация в setup
watch(
() => props.timeout,
(newTimeout) => {
if (newTimeout < 0) {
console.warn('Timeout must be positive');
}
}
);
</script>
Различие: required vs default
// ОБЯЗАТЕЛЬНЫЙ prop (нет default)
const props = withDefaults(defineProps<{
title: string; // обязательно передать
}>()), {});
// ОПЦИОНАЛЬНЫЙ с default
const props = withDefaults(defineProps<{
title?: string; // опционально, если есть default
}>()), {
title: 'Default Title'
});
Правила для значений по умолчанию
1. Для примитивов — просто значение
withDefaults(defineProps<{
count?: number;
text?: string;
active?: boolean;
}>()), {
count: 0,
text: 'hello',
active: true
})
2. Для массивов и объектов — функция
// НЕПРАВИЛЬНО: все экземпляры компонента будут делить один массив
withDefaults(defineProps<{
items?: string[];
}>()), {
items: [] // ПЛОХО!
})
// ПРАВИЛЬНО: каждый компонент получит свой массив
withDefaults(defineProps<{
items?: string[];
}>()), {
items: () => [] // ХОРОШО
})
// Для объектов тоже
withDefaults(defineProps<{
config?: { timeout: number; retries: number };
}>()), {
config: () => ({ timeout: 3000, retries: 3 })
})
Примеры с разными типами
<script setup lang="ts">
interface Props {
// Примитивы
title?: string;
count?: number;
active?: boolean;
// Коллекции
tags?: string[];
config?: Record<string, any>;
// Функции
onSubmit?: (data: any) => void;
// Union типы
variant?: 'primary' | 'secondary' | 'danger';
size?: 'sm' | 'md' | 'lg';
// Nullable
user?: { id: number; name: string } | null;
}
const props = withDefaults(defineProps<Props>()), {
title: 'Default Title',
count: 0,
active: false,
tags: () => [],
config: () => ({ theme: 'light' }),
variant: 'primary',
size: 'md',
user: null
});
</script>
Использование в компоненте
<!-- Родительский компонент -->
<template>
<!-- Переданы все значения явно -->
<MyComponent
title="Custom Title"
:count="10"
:disabled="true"
:items="['a', 'b', 'c']"
mode="dark"
/>
<!-- Используются значения по умолчанию -->
<MyComponent title="Simple" />
<!-- Смешанно -->
<MyComponent
title="Mixed"
:count="5"
<!-- остальное из defaults -->
/>
</template>
Сравнение с React
В React это работает иначе — через деструктуризацию props:
// React
interface MyComponentProps {
title: string;
count?: number;
disabled?: boolean;
items?: string[];
mode?: 'dark' | 'light';
}
function MyComponent({
title,
count = 0,
disabled = false,
items = [],
mode = 'light'
}: MyComponentProps) {
return (
<div>
<h1>{title}</h1>
<p>Count: {count}</p>
</div>
);
}
// ИЛИ через Object.assign
function MyComponent(props: MyComponentProps) {
const merged = {
count: 0,
disabled: false,
items: [],
mode: 'light' as const,
...props
};
return <div>{merged.title}</div>;
}
Best Practices для Vue
1. Используй withDefaults для TypeScript
✓ const props = withDefaults(defineProps<Props>()), { ... });
✗ const props = defineProps({ ... }); // менее типобезопасно
2. Помни о функциях для изменяемых значений
// ✓ Правильно
withDefaults(defineProps<{
items?: string[];
}>()), {
items: () => []
})
// ✗ Неправильно — утечка состояния между компонентами
withDefaults(defineProps<{
items?: string[];
}>()), {
items: [] // все компоненты делят один массив!
})
3. Валидируй значения при необходимости
// Для сложной валидации используй computed
const isValidTimeout = computed(() => {
return props.timeout > 0 && props.timeout < 60000;
});
watch(
() => props.timeout,
(newVal) => {
if (!isValidTimeout.value) {
console.warn('Invalid timeout');
}
}
);
4. Документируй props
/**
* MyComponent
*
* @prop {string} title - компонента
* @prop {number} [count=0] - счётчик
* @prop {boolean} [disabled=false] - отключить ли
* @prop {string[]} [items=[]] - список элементов
* @prop {'light'|'dark'} [mode='light'] - тема
*/
const props = withDefaults(defineProps<Props>()), { ... });
Итог
Значения по умолчанию в Vue defineProps:
-
withDefaults — рекомендуемый способ (Vue 3.3+)
- Типобезопасен
- Читаемый код
- Поддерживает все типы
-
defineProps с объектом — классический способ
- Работает в JavaScript
- Позволяет добавить валидацию
- Более многословен
-
Помни о функциях для массивов и объектов
- Избегаешь утечек состояния
- Каждый компонент получает свою копию
-
Типизируй правильно — используй интерфейсы TypeScript
Это хорошая практика в Vue, как и иммутабельность в React!