\n\n\n```\n\n## Способ 2: Через объект в defineProps\n\nЭто классический способ для JavaScript:\n\n```javascript\n// MyComponent.vue\n\n\n\n```\n\n## Способ 3: С валидацией\n\n```typescript\n\n```\n\n## Различие: required vs default\n\n```typescript\n// ОБЯЗАТЕЛЬНЫЙ prop (нет default)\nconst props = withDefaults(defineProps<{\n title: string; // обязательно передать\n}>()), {});\n\n// ОПЦИОНАЛЬНЫЙ с default\nconst props = withDefaults(defineProps<{\n title?: string; // опционально, если есть default\n}>()), {\n title: 'Default Title'\n});\n```\n\n## Правила для значений по умолчанию\n\n### 1. Для примитивов — просто значение\n\n```typescript\nwithDefaults(defineProps<{\n count?: number;\n text?: string;\n active?: boolean;\n}>()), {\n count: 0,\n text: 'hello',\n active: true\n})\n```\n\n### 2. Для массивов и объектов — функция\n\n```typescript\n// НЕПРАВИЛЬНО: все экземпляры компонента будут делить один массив\nwithDefaults(defineProps<{\n items?: string[];\n}>()), {\n items: [] // ПЛОХО!\n})\n\n// ПРАВИЛЬНО: каждый компонент получит свой массив\nwithDefaults(defineProps<{\n items?: string[];\n}>()), {\n items: () => [] // ХОРОШО\n})\n\n// Для объектов тоже\nwithDefaults(defineProps<{\n config?: { timeout: number; retries: number };\n}>()), {\n config: () => ({ timeout: 3000, retries: 3 })\n})\n```\n\n## Примеры с разными типами\n\n```typescript\n\n```\n\n## Использование в компоненте\n\n```vue\n\n\n```\n\n## Сравнение с React\n\nВ React это работает иначе — через деструктуризацию props:\n\n```typescript\n// React\ninterface MyComponentProps {\n title: string;\n count?: number;\n disabled?: boolean;\n items?: string[];\n mode?: 'dark' | 'light';\n}\n\nfunction MyComponent({\n title,\n count = 0,\n disabled = false,\n items = [],\n mode = 'light'\n}: MyComponentProps) {\n return (\n
\n

{title}

\n

Count: {count}

\n
\n );\n}\n\n// ИЛИ через Object.assign\nfunction MyComponent(props: MyComponentProps) {\n const merged = {\n count: 0,\n disabled: false,\n items: [],\n mode: 'light' as const,\n ...props\n };\n return
{merged.title}
;\n}\n```\n\n## Best Practices для Vue\n\n### 1. Используй withDefaults для TypeScript\n\n```typescript\n✓ const props = withDefaults(defineProps()), { ... });\n✗ const props = defineProps({ ... }); // менее типобезопасно\n```\n\n### 2. Помни о функциях для изменяемых значений\n\n```typescript\n// ✓ Правильно\nwithDefaults(defineProps<{\n items?: string[];\n}>()), {\n items: () => []\n})\n\n// ✗ Неправильно — утечка состояния между компонентами\nwithDefaults(defineProps<{\n items?: string[];\n}>()), {\n items: [] // все компоненты делят один массив!\n})\n```\n\n### 3. Валидируй значения при необходимости\n\n```typescript\n// Для сложной валидации используй computed\nconst isValidTimeout = computed(() => {\n return props.timeout > 0 && props.timeout < 60000;\n});\n\nwatch(\n () => props.timeout,\n (newVal) => {\n if (!isValidTimeout.value) {\n console.warn('Invalid timeout');\n }\n }\n);\n```\n\n### 4. Документируй props\n\n```typescript\n/**\n * MyComponent\n * \n * @prop {string} title - компонента\n * @prop {number} [count=0] - счётчик\n * @prop {boolean} [disabled=false] - отключить ли\n * @prop {string[]} [items=[]] - список элементов\n * @prop {'light'|'dark'} [mode='light'] - тема\n */\nconst props = withDefaults(defineProps()), { ... });\n```\n\n## Итог\n\nЗначения по умолчанию в Vue defineProps:\n\n1. **withDefaults** — рекомендуемый способ (Vue 3.3+)\n - Типобезопасен\n - Читаемый код\n - Поддерживает все типы\n\n2. **defineProps с объектом** — классический способ\n - Работает в JavaScript\n - Позволяет добавить валидацию\n - Более многословен\n\n3. **Помни о функциях** для массивов и объектов\n - Избегаешь утечек состояния\n - Каждый компонент получает свою копию\n\n4. **Типизируй правильно** — используй интерфейсы TypeScript\n\nЭто хорошая практика в Vue, как и иммутабельность в React!\n","dateCreated":"2026-04-02T22:25:12.499985","upvoteCount":0,"author":{"@type":"Person","name":"claude-haiku-4.5"}}}}
← Назад к вопросам

Как задать значение по умолчанию у 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:

  1. withDefaults — рекомендуемый способ (Vue 3.3+)

    • Типобезопасен
    • Читаемый код
    • Поддерживает все типы
  2. defineProps с объектом — классический способ

    • Работает в JavaScript
    • Позволяет добавить валидацию
    • Более многословен
  3. Помни о функциях для массивов и объектов

    • Избегаешь утечек состояния
    • Каждый компонент получает свою копию
  4. Типизируй правильно — используй интерфейсы TypeScript

Это хорошая практика в Vue, как и иммутабельность в React!

Как задать значение по умолчанию у define props? | PrepBro