Vue 3.3 이상의 최신 문법에

2024. 11. 18. 09:05Vue

Vue 3.3 이상의 최신 문법에 대해 구조, 정의, 사용법, 예제를 정리한 자료

Vue 3.3 최신 문법

1. defineModel

구조

const model = defineModel(name, options);

정의

  • defineModel은 컴포넌트에서 v-model을 간단하게 정의할 수 있는 문법입니다.
  • 다중 v-model을 쉽게 구현할 수 있습니다.

사용법

  • name: v-model 이름을 정의.
  • options: 타입, 기본값 등을 포함하는 객체.

예제

1) 기본 사용

<script setup>
const title = defineModel('title', { type: String, default: '' });
</script>

<template>
  <input v-model="title" placeholder="Enter title" />
</template>

2) 다중 v-model 사용

<script setup>
const title = defineModel('title', { type: String, default: '' });
const content = defineModel('content', { type: String, default: '' });
</script>

<template>
  <input v-model="title" placeholder="Enter title" />
  <textarea v-model="content" placeholder="Enter content"></textarea>
</template>

3) 부모와 연결

<template>
  <ChildComponent v-model:title="title" v-model:content="content" />
</template>

<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';

const title = ref('');
const content = ref('');
</script>

2. defineOptions

구조

defineOptions(options);

정의

  • defineOptions는 컴포넌트의 옵션(name, inheritAttrs 등)을 설정하는 문법입니다.
  • script setup 내에서 컴포넌트 옵션을 정의할 수 있습니다.

사용법

  • options: 컴포넌트 이름, 속성 상속 여부 등.

예제

1) 컴포넌트 이름 설정

<script setup>
defineOptions({
  name: 'MyComponent',
});
</script>

<template>
  <p>This is MyComponent</p>
</template>

2) 속성 상속 비활성화

<script setup>
defineOptions({
  inheritAttrs: false,
});
</script>

<template>
  <p>Attributes will not be inherited.</p>
</template>

3) 이름과 속성 함께 설정

<script setup>
defineOptions({
  name: 'CustomButton',
  inheritAttrs: false,
});
</script>

<template>
  <button>This is a custom button</button>
</template>

3. defineSlots

구조

defineSlots<SlotStructure>();

정의

  • defineSlots는 컴포넌트의 슬롯 구조를 선언하고 타입을 명시적으로 정의합니다.
  • TypeScript와 함께 사용하면 타입 안전성을 제공합니다.

사용법

  • SlotStructure: 슬롯 이름과 해당 데이터의 타입을 정의.

예제

1) 단일 슬롯 정의

<script setup>
defineSlots<{
  default: { message: string }
}>();
</script>

<template>
  <slot :message="'Hello from slot'" />
</template>

2) 다중 슬롯 정의

<script setup>
defineSlots<{
  header: { title: string },
  footer?: { copyright: string },
}>();
</script>

<template>
  <slot name="header" :title="'Header Title'" />
  <slot name="footer" :copyright="'© 2024'" />
</template>

3) 부모 컴포넌트와 함께 사용

<template>
  <ChildComponent>
    <template #header="{ title }">
      <h1>{{ title }}</h1>
    </template>
    <template #footer="{ copyright }">
      <p>{{ copyright }}</p>
    </template>
  </ChildComponent>
</template>

Vue 3.3+ 최신 문법 가이드

====================

1. defineModel


정의

defineModel은 v-model 바인딩을 컴포넌트에서 더 쉽게 구현할 수 있게 해주는 새로운 매크로

사용법

// 기본 사용
const model = defineModel()

// 옵션 지정
const model = defineModel({
  type: String,
  default: '',
  required: true
})

// 여러 v-model
const title = defineModel('title')
const content = defineModel('content')

예제

// 예제 1: 기본 입력 컴포넌트
<script setup>
const model = defineModel()
</script>

<template>
  <input v-model="model" class="input" />
</template>

// 예제 2: 숫자 입력 컴포넌트
<script setup>
const model = defineModel({
  type: Number,
  default: 0,
  validator: (value) => value >= 0
})
</script>

<template>
  <input 
    type="number" 
    v-model="model" 
    min="0"
  />
</template>

// 예제 3: 다중 v-model 폼
<script setup>
const firstName = defineModel('firstName')
const lastName = defineModel('lastName')
const email = defineModel('email')
</script>

<template>
  <form>
    <input v-model="firstName" placeholder="이름" />
    <input v-model="lastName" placeholder="성" />
    <input v-model="email" placeholder="이메일" />
  </form>
</template>

2. Props 타입 선언 개선


정의

TypeScript와 함께 사용할 때 props의 타입을 더 유연하고 직관적으로 선언할 수 있습니다.

사용법

// 인터페이스 사용
interface Props {
  name: string
  age?: number
}

// 제네릭 사용
interface Props<T> {
  items: T[]
  selected: T
}

// withDefaults 사용
withDefaults(defineProps<Props>(), {
  age: 20
})

예제

// 예제 1: 기본 타입 선언
<script setup lang="ts">
interface Props {
  title: string
  count: number
  isActive?: boolean
}

const props = defineProps<Props>()
</script>

// 예제 2: 제네릭 컴포넌트
<script setup lang="ts">
interface Props<T> {
  items: T[]
  onSelect: (item: T) => void
}

const props = defineProps<Props<string>>()
</script>

// 예제 3: 복잡한 타입과 기본값
<script setup lang="ts">
interface User {
  id: number
  name: string
}

interface Props {
  users: User[]
  selectedId?: number
  searchTerm: string
}

const props = withDefaults(defineProps<Props>(), {
  selectedId: -1,
  searchTerm: ''
})
</script>

3. defineEmits 타입 개선


정의

이벤트 발신(emit)에 대한 타입 안전성이 향상되었으며, 더 명확한 타입 정의가 가능합니다.

사용법

// 타입으로 이벤트 정의
interface Emits {
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}

// 제네릭 이벤트
interface Emits<T> {
  (e: 'select', item: T): void
  (e: 'remove', id: number): void
}

예제

// 예제 1: 기본 이벤트 정의
<script setup lang="ts">
interface Emits {
  (e: 'update:modelValue', value: string): void
  (e: 'submit'): void
}

const emit = defineEmits<Emits>()

const handleInput = (e: Event) => {
  const value = (e.target as HTMLInputElement).value
  emit('update:modelValue', value)
}
</script>

// 예제 2: 제네릭 이벤트
<script setup lang="ts">
interface Item {
  id: number
  name: string
}

interface Emits {
  (e: 'select', item: Item): void
  (e: 'delete', id: number): void
}

const emit = defineEmits<Emits>()

const handleSelect = (item: Item) => {
  emit('select', item)
}
</script>

// 예제 3: 복잡한 이벤트 페이로드
<script setup lang="ts">
interface FilterPayload {
  search: string
  category: string
  page: number
}

interface Emits {
  (e: 'filter', payload: FilterPayload): void
  (e: 'reset'): void
}

const emit = defineEmits<Emits>()

const applyFilter = (filterData: FilterPayload) => {
  emit('filter', filterData)
}
</script>

4. Reactive Props Destructuring


정의

Props를 구조 분해할 때 반응성을 유지하면서 더 깔끔한 코드를 작성할 수 있습니다.

사용법

// 기본 구조 분해
const { title, description } = defineProps(['title', 'description'])

// 타입과 함께 사용
const { name, age } = defineProps<{
  name: string
  age: number
}>()

// 기본값 설정
const { status = 'active' } = defineProps(['status'])

예제

// 예제 1: 기본 사용
<script setup>
const { title, subtitle } = defineProps({
  title: String,
  subtitle: String
})
</script>

<template>
  <div>
    <h1>{{ title }}</h1>
    <h2>{{ subtitle }}</h2>
  </div>
</template>

// 예제 2: 타입과 기본값
<script setup lang="ts">
interface Props {
  name: string
  age?: number
  role?: 'admin' | 'user'
}

const { name, age = 20, role = 'user' } = defineProps<Props>()
</script>

// 예제 3: 계산된 속성과 함께 사용
<script setup>
const { items, selectedId } = defineProps(['items', 'selectedId'])

const selectedItem = computed(() => 
  items.find(item => item.id === selectedId)
)
</script>

'Vue' 카테고리의 다른 글

new FormData() 의 특별한 활용법  (0) 2024.11.21
const로 필드를 매번 만든 것보다는  (0) 2024.11.19
defineModel, v-model 3.3최신문  (0) 2024.11.17
Quasar checkbox  (0) 2024.11.07
django와 vue.js <script setup> csrfToken처리 방법  (0) 2024.11.07