3. vue version 3.3

  1. props destructuring
  2. defineModel
  3. better TS support
  4. ... and more !!

1. props destructuring / default value

propsdestructuring하면서 default value도 세팅할 수 있다.

// version 3.3
const { msg = 'default val', name } = defineProps<{
    msg?: string;
    name?: string;
}>();
// before
const props = defineProps<{
    msg?: string;
    name?: string;
}>()
// for default value // before
const props = withDefaults(
    defineProps<{
        msg?: string;
        name?: string
    }>(),
    {
        msg: 'subscribe',
        name: 'hyungju-lee',
    }
)
// for default value // for destructuring // for reactive // before
const { msg, name } = toRefs(
    withDefaults(
        defineProps<{
            msg?: string;
            name?: string
        }>(),
        {
            msg: 'subscribe',
            name: 'hyungju-lee',
        }
    )
)
// version 3.3
const { msg = 'subscribe', name = 'hyungju-lee' } = defineProps<{
    msg?: string;
    name?: string;
}>();

2. defineModel

defineModel
<script setup lang="ts">
const modelValue = defineModel<string>();
</script>

<template>
  <div>
    <input type="text" v-model="modelValue">
  </div>
</template>

3. export define props

types.d.ts
export type BaseProps = {
    testId: string
}

4. generic

<script setup lang="ts" generic="T">
defineProps<{
  items: T[]
}>();
</script>
GenericList.vue
<script setup lang="ts" generic="T">
defineProps<{
  items: T[];
  keyField: keyof T;
}>();

defineEmits<{
  (e: 'delete', item: T): void
}>();
</script>

<template>
  <ul class="flex flex-col">
    <li 
        v-for="item in items"
        :key="String(item[keyField as keyof T])"
        class="flex items-center"
    >
      <button @click="$emit('delete', item)" class="text-red-500">
        <IconAccountBox />
      </button>
      <slot :item="item"></slot>
    </li>
  </ul>
</template>