Skip to content

<script setup> ​

<script setup> āĻšāϞ āϏāĻŋāĻ™ā§āϗ⧇āϞ-āĻĢāĻžāχāϞ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϏ (SFCs) āĻāϰ āĻŽāĻ§ā§āϝ⧇ āĻ•āĻŽā§āĻĒā§‹āϜāĻŋāĻļāύ⧇āϰ API āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āĻ•āĻŽā§āĻĒāĻžāχāϞ-āϟāĻžāχāĻŽ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•āϟāĻŋāĻ• āϏ⧁āĻ—āĻžāϰāĨ¤ āφāĻĒāύāĻŋ āϝāĻĻāĻŋ SFCs āĻāĻŦāĻ‚ Composition API āωāĻ­āϝāĻŧāχ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇āύ āϤāĻŦ⧇ āĻāϟāĻŋ āϰāĻŋāϕ⧋āĻŽā§‡āĻ¨ā§āĻĄā§‡āĻĄ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏāĨ¤ āĻāϟāĻŋ āϏāĻžāϧāĻžāϰāĻŖ <script> āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ⧇āϰ āϤ⧁āϞāύāĻžāϝāĻŧ āĻ…āύ⧇āĻ• āϏ⧁āĻŦāĻŋāϧāĻž āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇:

  • āϞ⧇āϏ āĻŦāϝāĻŧāϞāĻžāϰāĻĒā§āϞ⧇āϟ āϏāĻš āφāϰāĻ“ āϏāĻ‚āĻ•ā§āώāĻŋāĻĒā§āϤ āϕ⧋āĻĄ
  • āĻĒāĻŋāωāϰ āϟāĻžāχāĻĒāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻĒā§āϰāĻĒāϏ āĻāĻŦāĻ‚ āύāĻŋāĻ°ā§āĻ—āϤ āχāϭ⧇āĻ¨ā§āϟ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻ•āϰāĻžāϰ āĻ•ā§āώāĻŽāϤāĻž
  • āĻ­āĻžāϞ āϰāĻžāύāϟāĻžāχāĻŽ āĻĒāĻžāϰāĻĢāϰāĻŽā§āϝāĻžāĻ¨ā§āϏ (āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟāϟāĻŋ āĻāĻ•āχ āϏ⧁āϝ⧋āϗ⧇ āĻāĻ•āϟāĻŋ āϰ⧇āĻ¨ā§āĻĄāĻžāϰ āĻĢāĻžāĻ‚āĻļāύ⧇ āĻ•āĻŽā§āĻĒāĻžāχāĻ˛ā§āĻĄ āĻšāϝāĻŧ, āĻāĻ•āϟāĻŋ āĻŽāĻ§ā§āϝāĻŦāĻ°ā§āϤ⧀ āĻĒā§āϰāĻ•ā§āϏāĻŋ āĻ›āĻžāĻĄāĻŧāĻžāχ)
  • āφāϰāĻ“ āĻ­āĻžāϞ āφāχāĻĄāĻŋāχ āϟāĻžāχāĻĒ-āχāύāĻĢāĻžāϰ⧇āĻ¨ā§āϏ āĻĒāĻžāϰāĻĢāϰāĻŽā§āϝāĻžāĻ¨ā§āϏ (āϕ⧋āĻĄ āĻĨ⧇āϕ⧇ āϟāĻžāχāĻĒāϗ⧁āϞāĻŋ āĻŦ⧇āϰ āĻ•āϰāϤ⧇ āĻ˛ā§āϝāĻžāĻ™ā§āĻ—ā§ā§Ÿā§‡āϜ āϏāĻžāĻ°ā§āĻ­āĻžāϰ⧇āϰ āϜāĻ¨ā§āϝ āĻ•āĻŽ āĻ•āĻžāϜ)

Basic Syntax ​

āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ⧇ opt-in āĻ•āϰāϤ⧇, <script> āĻŦā§āϞāϕ⧇ setup āĻ…ā§āϝāĻžāĻŸā§āϰāĻŋāĻŦāĻŋāωāϟ āϝ⧋āĻ— āĻ•āϰ⧁āύ:

vue
<script setup>
console.log('hello script setup')
</script>

āĻ­āĻŋāϤāϰ⧇āϰ āϕ⧋āĻĄāϟāĻŋ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϰ setup() āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻ•āĻ¨ā§āĻŸā§‡āĻ¨ā§āϟ āĻšāĻŋāϏ⧇āĻŦ⧇ āĻ•āĻŽā§āĻĒāĻžāχāϞ āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤ āĻāϰ āĻŽāĻžāύ⧇ āĻšāϞ āϝ⧇ āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ• <script> āĻĨ⧇āϕ⧇ āĻ­āĻŋāĻ¨ā§āύ, āϝ⧇āϟāĻŋ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āĻāĻ•āĻŦāĻžāϰ āĻāĻ•ā§āϏāĻŋāĻ•āĻŋāωāϟ āĻšāϝāĻŧ āϝāĻ–āύ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϟāĻŋ āĻĒā§āϰāĻĨāĻŽ āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āĻ•āϰāĻž āĻšāϝāĻŧ, <script setup>-āĻāϰ āĻ­āĻŋāϤāϰ⧇āϰ āϕ⧋āĻĄāϟāĻŋ āĻĒā§āϰāϤāĻŋāĻŦāĻžāϰ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϰ āĻāĻ•āϟāĻŋ āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ āϤ⧈āϰāĻŋ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻ•ā§āϏāĻŋāĻ•āĻŋāωāϟ āĻ•āϰāĻŦ⧇āĨ¤

Top-level bindings are exposed to template ​

<script setup> āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, <script setup>-āĻāϰ āĻ­āĻŋāϤāϰ⧇ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāϰāĻĄ āϝ⧇āϕ⧋āύ⧋ āϟāĻĒ-āϞ⧇āϭ⧇āϞ āĻŦāĻžāχāĻ¨ā§āĻĄāĻŋāĻ‚ (āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ, āĻĢāĻžāĻ‚āĻļāύ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻāĻŦāĻ‚ āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āϏāĻš) āϏāϰāĻžāϏāϰāĻŋ āĻŸā§‡āĻŽāĻĒā§āϞ⧇āĻŸā§‡ āĻŦā§āϝāĻŦāĻšāĻžāϰāϝ⧋āĻ—ā§āϝ:

vue
<script setup>
// variable
const msg = 'Hello!'

// functions
function log() {
  console.log(msg)
}
</script>

<template>
  <button @click="log">{{ msg }}</button>
</template>

āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āĻāĻ•āχ āϧāĻžāϰāĻžāϝāĻŧ āωāĻ¨ā§āĻŽā§āĻ•ā§āϤ āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤ āĻāϰ āĻŽāĻžāύ⧇ āĻšāϞ āφāĻĒāύāĻŋ āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟ āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ⧇ āĻāĻ•āϟāĻŋ āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āĻ•āϰāĻž āϏāĻšāĻžāϝāĻŧāĻ• āĻĢāĻžāĻ‚āĻļāύ āϏāϰāĻžāϏāϰāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ āĻāϟāĻŋāϕ⧇ methods āĻ…āĻĒāĻļāύ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻĒā§āϰāĻ•āĻžāĻļ āύāĻž āĻ•āϰ⧇āχ:

vue
<script setup>
import { capitalize } from './helpers'
</script>

<template>
  <div>{{ capitalize('hello') }}</div>
</template>

Reactivity ​

Reactivity APIs āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϰāĻŋā§Ÿā§‡āĻ•ā§āϟāĻŋāĻ­ āĻ¸ā§āĻŸā§‡āϟ āĻ¸ā§āĻĒāĻˇā§āϟāĻ­āĻžāĻŦ⧇ āϤ⧈āϰāĻŋ āĻ•āϰāĻž āĻĒā§āϰāϝāĻŧā§‹āϜāύāĨ¤ āĻāĻ•āϟāĻŋ setup() āĻĢāĻžāĻ‚āĻļāύ āĻĨ⧇āϕ⧇ āϰāĻŋāϟāĻžāĻ°ā§āύāĻĄ āĻ­ā§āϝāĻžāϞ⧁āϗ⧁āϞāĻŋāϰ āĻ…āύ⧁āϰ⧂āĻĒ, āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟāϗ⧁āϞāĻŋāϤ⧇ āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰāĻž āĻšāϞ⧇ āϰ⧇āĻĢāϗ⧁āϞāĻŋ āĻ¸ā§āĻŦāϝāĻŧāĻ‚āĻ•ā§āϰāĻŋāϝāĻŧāĻ­āĻžāĻŦ⧇ unwrapped āĻšāϝāĻŧ:

vue
<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>

Using Components ​

<script setup> āĻāϰ āĻ¸ā§āϕ⧋āĻĒ āĻ­ā§āϝāĻžāϞ⧁āϗ⧁āϞāĻŋ āϏāϰāĻžāϏāϰāĻŋ āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡ āĻŸā§āϝāĻžāĻ— āύ⧇āχāĻŽ āĻšāĻŋāϏāĻžāĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇:

vue
<script setup>
import MyComponent from './MyComponent.vue'
</script>

<template>
  <MyComponent />
</template>

āĻŽāύ⧇ āĻ•āϰ⧁āύ MyComponent āĻāĻ•āϟāĻŋ āĻ­ā§āϝāĻžāϰāĻŋā§Ÿā§‡āĻŦāϞ āĻšāĻŋāϏāĻžāĻŦ⧇ āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰāĻž āĻšāĻšā§āϛ⧇ āĨ¤ āφāĻĒāύāĻŋ āϝāĻĻāĻŋ JSX āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻĨāĻžāϕ⧇āύ, āϤāĻžāĻšāϞ⧇ āĻŽā§‡āĻ¨ā§āϟāĻžāϞ āĻŽāĻĄā§‡āϞ āĻāĻ–āĻžāύ⧇ āĻāĻ•āχ āϰāĻ•āĻŽāĨ¤ kebab-case āϏāĻŽāϤ⧁āĻ˛ā§āϝ <my-component> āĻŸā§‡āĻŽāĻĒā§āϞ⧇āĻŸā§‡āĻ“ āĻ•āĻžāϜ āĻ•āϰ⧇ - āϤāĻŦ⧇ PascalCase āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻŸā§āϝāĻžāĻ—āϗ⧁āϞāĻŋ āĻĻ⧃āĻĸāĻŧāĻ­āĻžāĻŦ⧇ āϏāĻžāĻŽāĻžā§āϜāĻ¸ā§āϝ⧇āϰ āϜāĻ¨ā§āϝ āϰāĻŋāϕ⧋āĻŽā§‡āĻ¨ā§āĻĄ āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤ āĻāϟāĻŋ āύ⧇āϟāĻŋāĻ­ āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻĨ⧇āϕ⧇ āĻĒāĻžāĻ°ā§āĻĨāĻ•ā§āϝ āĻ•āϰāϤ⧇ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰ⧇āĨ¤

Dynamic Components ​

āϝ⧇āĻšā§‡āϤ⧁ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋ āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āϕ⧀āϗ⧁āϞāĻŋāϰ āĻ…āϧ⧀āύ⧇ āϰ⧇āϜāĻŋāĻ¸ā§āĻŸā§āϰāĻžāĻĄ āύāĻž āĻšāϝāĻŧ⧇ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āĻšāĻŋāϏāĻžāĻŦ⧇ āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇, āϤāĻžāχ <script setup>-āĻāϰ āĻ­āĻŋāϤāϰ⧇ āĻĄāĻžāϝāĻŧāύāĻžāĻŽāĻŋāĻ• āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āφāĻŽāĻžāĻĻ⧇āϰ āĻĄāĻžāχāύāĻžāĻŽāĻŋāĻ• :is āĻŦāĻžāχāĻ¨ā§āĻĄāĻŋāĻ‚ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āωāϚāĻŋāϤ:

vue
<script setup>
import Foo from './Foo.vue'
import Bar from './Bar.vue'
</script>

<template>
  <component :is="Foo" />
  <component :is="someCondition ? Foo : Bar" />
</template>

āϞāĻ•ā§āĻˇā§āϝ āĻ•āϰ⧁āύ āĻ•āĻŋāĻ­āĻžāĻŦ⧇ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋāϕ⧇ āĻāĻ•āϟāĻŋ āϟāĻžāϰāύāĻžāϰāĻŋ āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ⧇ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ āĻšāĻŋāϏāĻžāĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤

Recursive Components ​

āĻāĻ•āϟāĻŋ āĻāϏāĻāĻĢāϏāĻŋ āϤāĻžāϰ āĻĢāĻžāχāϞ⧇āϰ āύāĻžāĻŽ āĻĻāĻŋāϝāĻŧ⧇ āĻ…āĻ¨ā§āϤāĻ°ā§āύāĻŋāĻšāĻŋāϤāĻ­āĻžāĻŦ⧇ āύāĻŋāĻœā§‡āϕ⧇ āϰ⧇āĻĢāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āϝ⧇āĻŽāύ FooBar.vue āύāĻžāĻŽā§‡āϰ āĻāĻ•āϟāĻŋ āĻĢāĻžāχāϞ āϤāĻžāϰ āĻŸā§‡āĻŽāĻĒā§āϞ⧇āĻŸā§‡ āύāĻŋāĻœā§‡āϕ⧇ <FooBar/> āĻšāĻŋāϏ⧇āĻŦ⧇ āϰ⧇āĻĢāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤

āύ⧋āϟ āĻ•āϰ⧁āύ āĻāϟāĻŋ āχāĻŽā§āĻĒā§‹āĻ°ā§āĻŸā§‡āĻĄ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϰ āϤ⧁āϞāύāĻžāϝāĻŧ āĻ•āĻŽ āĻ…āĻ—ā§āϰāĻžāϧāĻŋāĻ•āĻžāϰ āϰāϝāĻŧ⧇āϛ⧇āĨ¤ āφāĻĒāύāĻžāϰ āϝāĻĻāĻŋ āĻāĻ•āϟāĻŋ āύ⧇āχāĻŽāĻĄ āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āĻĨāĻžāϕ⧇ āϝāĻž āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϟāĻŋāϰ āĻ…āύ⧁āĻŽāĻŋāϤ āύāĻžāĻŽā§‡āϰ āϏāĻžāĻĨ⧇ āĻ•āύāĻĢā§āϞāĻŋāĻ•ā§āϟ āĻ•āϰ⧇, āφāĻĒāύāĻŋ āχāĻŽā§āĻĒā§‹āĻ°ā§āĻŸā§‡āϰ āύāĻžāĻŽ āĻĻāĻŋāϤ⧇ āĻĒāĻžāϰ⧇āύ:

js
import { FooBar as FooBarChild } from './components'

Namespaced Components ​

āφāĻĒāύāĻŋ āĻ…āĻŦāĻœā§‡āĻ•ā§āĻŸā§‡āϰ āĻĒā§āϰ⧋āĻĒāĻžāĻ°ā§āϟāĻŋāϰ āĻ…āϧ⧀āύ⧇ āύ⧇āĻ¸ā§āϟ āĻ•āϰāĻž āϕ⧋āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϗ⧁āϞāĻŋāϕ⧇ āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰāϤ⧇ <Foo.Bar> āĻāϰ āĻŽāϤ⧋ āĻĄāϟ āϏāĻš āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻŸā§āϝāĻžāĻ— āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤ āφāĻĒāύāĻŋ āϝāĻ–āύ āĻāĻ•āϟāĻŋ āĻĢāĻžāχāϞ āĻĨ⧇āϕ⧇ āĻāĻ•āĻžāϧāĻŋāĻ• āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āĻ•āϰ⧇āύ āϤāĻ–āύ āĻāϟāĻŋ āĻĻāϰāĻ•āĻžāϰ⧀:

vue
<script setup>
import * as Form from './form-components'
</script>

<template>
  <Form.Input>
    <Form.Label>label</Form.Label>
  </Form.Input>
</template>

Using Custom Directives ​

āĻ—ā§āϞ⧋āĻŦāĻžāϞāĻŋ āϰ⧇āϜāĻŋāĻ¸ā§āĻŸā§āϰāĻžāĻĄ āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻĄāĻŋāϰ⧇āĻ•ā§āϟāĻŋāĻ­āϗ⧁āϞ⧋ āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ• āĻšāĻŋāϏāĻžāĻŦ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤ āϞ⧋āĻ•āĻžāϞ āĻ•āĻžāĻ¸ā§āϟāĻŽ āϕ⧇ <script setup>-āĻāϰ āϏāĻžāĻĨ⧇ āĻ¸ā§āĻĒāĻˇā§āϟāĻ­āĻžāĻŦ⧇ āϰ⧇āϜāĻŋāĻ¸ā§āĻŸā§āϰāĻžāĻĄ āĻšāĻ“āϝāĻŧāĻžāϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āύ⧇āχ, āϤāĻŦ⧇ āϤāĻžāĻĻ⧇āϰ āĻ…āĻŦāĻļā§āϝāχ āύ⧇āχāĻŽāĻŋāĻ‚ āĻ¸ā§āĻ•āĻŋāĻŽ vNameOfDirective āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇:

vue
<script setup>
const vMyDirective = {
  beforeMount: (el) => {
    // do something with the element
  }
}
</script>
<template>
  <h1 v-my-directive>This is a Heading</h1>
</template>

āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻ…āĻ¨ā§āϝ āϕ⧋āĻĨāĻžāĻ“ āĻĨ⧇āϕ⧇ āĻāĻ•āϟāĻŋ āĻĄāĻŋāϰ⧇āĻ•ā§āϟāĻŋāĻ­ āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āĻ•āϰ⧇ āĻĨāĻžāϕ⧇āύ, āϤāĻžāĻšāϞ⧇ āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧀āϝāĻŧ āύ⧇āχāĻŽāĻŋāĻ‚ āĻ¸ā§āĻ•āĻŋāĻŽā§‡āϰ āϏāĻžāĻĨ⧇ āĻŽāĻžāύāĻžāύāϏāχ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻāϟāĻŋāϰ āύāĻžāĻŽ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇:

vue
<script setup>
import { myDirective as vMyDirective } from './MyDirective.js'
</script>

defineProps() & defineEmits() ​

āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻĒā§āϰāĻ•āĻžāϰ⧇āϰ āĻ…āύ⧁āĻŽāĻžāύ āϏāĻŽāĻ°ā§āĻĨāύ āϏāĻš props āĻāĻŦāĻ‚ emits āĻāϰ āĻŽāϤ⧋ āĻ…āĻĒāĻļāύ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻ•āϰāϤ⧇, āφāĻŽāϰāĻž defineProps āĻāĻŦāĻ‚ defineEmits āĻāĻĒāĻŋāφāχ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŋ, āϝāĻž <script setup>-āĻāϰ āĻŽāĻ§ā§āϝ⧇ āĻ…āĻŸā§‹āĻŽā§‡āϟāĻŋāĻ•ā§āϞāĻŋ āĻ…ā§āϝāĻžāĻ­āĻžāχāϞāĻāĻŦāϞ āĻšāĻŦ⧇:

vue
<script setup>
const props = defineProps({
  foo: String
})

const emit = defineEmits(['change', 'delete'])
// setup code
</script>
  • defineProps āĻāĻŦāĻ‚ defineEmits āĻšāϞ āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋ āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ <script setup>-āĻāϰ āĻŽāĻ§ā§āϝ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰāϝ⧋āĻ—ā§āϝāĨ¤ āϏ⧇āϗ⧁āϞāĻŋ āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āĻ•āϰāĻžāϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āύ⧇āχ āĻāĻŦāĻ‚ <script setup> āĻĒā§āϰāĻ•ā§āϰāĻŋāϝāĻŧāĻž āĻ•āϰāĻž āĻšāϞ⧇ āĻ•āĻŽā§āĻĒāĻžāχāϞ āĻ•āϰāĻž āĻšāϝāĻŧāĨ¤

  • defineProps props āĻ…āĻĒāĻļāύ⧇āϰ āĻŽāϤ⧋ āĻāĻ•āχ āĻ­ā§āϝāĻžāϞ⧁ āĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇, āϝāĻ–āύ defineEmits emits āĻ…āĻĒāĻļāύ⧇āϰ āĻŽāϤ⧋ āĻāĻ•āχ āĻ­ā§āϝāĻžāϞ⧁ āĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇āĨ¤

  • defineProps āĻāĻŦāĻ‚ defineEmits āĻĒāĻžāϏ āĻ•āϰāĻž āĻ…āĻĒāĻļāύāϗ⧁āϞāĻŋāϰ āωāĻĒāϰ āĻ­āĻŋāĻ¤ā§āϤāĻŋ āĻ•āϰ⧇ āϏāĻ āĻŋāĻ• āϟāĻžāχāĻĒ⧇āϰ āχāύāĻĢāĻžāϰ⧇āĻ¨ā§āϏ āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇āĨ¤

  • defineProps āĻāĻŦāĻ‚ defineEmits-āĻ āĻĒāĻžāϏ āĻ•āϰāĻž āĻ…āĻĒāĻļāύāϗ⧁āϞāĻŋ āϏ⧇āϟāφāĻĒ⧇āϰ āĻŦāĻžāχāϰ⧇ āĻŽāĻĄāĻŋāωāϞ āĻ¸ā§āϕ⧋āĻĒ⧇ āĻšā§‹āχāĻ¸ā§āĻŸā§‡āĻĄ āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤ āĻ…āϤāĻāĻŦ, āĻ…āĻĒāĻļāύāϗ⧁āϞāĻŋ āϏ⧇āϟāφāĻĒ āϏ⧁āϝ⧋āϗ⧇ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāĻĄ āϞ⧋āĻ•āĻžāϞ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞ⧇āϰ āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇ āύāĻžāĨ¤ āĻāϟāĻŋ āĻ•āϰāĻžāϰ āĻĢāϞ⧇ āĻāĻ•āϟāĻŋ āĻ•āĻŽā§āĻĒāĻžāχāϞ āĻāϰāϰ āĻšāĻŦ⧇āĨ¤ āϝāĻžāχāĻšā§‹āĻ•, it can reference āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āĻ•āϰāĻž āĻŦāĻžāχāĻ¨ā§āĻĄāĻŋāĻ‚ āϝ⧇āĻšā§‡āϤ⧁ āϤāĻžāϰāĻž āĻŽāĻĄāĻŋāωāϞ āĻ¸ā§āϕ⧋āĻĒ āϰāϝāĻŧ⧇āϛ⧇āĨ¤

Type-only props/emit declarations ​

'defineProps' āĻŦāĻž 'defineEmits'-āĻ āĻāĻ•āϟāĻŋ āφāĻ•ā§āώāϰāĻŋāĻ• āϟāĻžāχāĻĒ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āĻĒāĻžāϏ āĻ•āϰ⧇ āĻĒāĻŋāωāϰ-āϟāĻžāχāĻĒ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻĒā§āϰāĻĒāϏ āĻāĻŦāĻ‚ āχāĻŽāĻŋāϟ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇:

ts
const props = defineProps<{
  foo: string
  bar?: number
}>()

const emit = defineEmits<{
  (e: 'change', id: number): void
  (e: 'update', value: string): void
}>()

// 3.3+: alternative, more succinct syntax
const emit = defineEmits<{
  change: [id: number] // named tuple syntax
  update: [value: string]
}>()
  • defineProps āĻŦāĻž defineEmits āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āϰāĻžāύāϟāĻžāχāĻŽ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻŦāĻž āϟāĻžāχāĻĒ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āĻāĻ•āχ āϏāĻŽāϝāĻŧ⧇ āωāĻ­āϝāĻŧ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āĻĢāϞ⧇ āĻāĻ•āϟāĻŋ āĻ•āĻŽā§āĻĒāĻžāχāϞ āĻāϰāϰ āĻšāĻŦ⧇āĨ¤

  • āϟāĻžāχāĻĒ āĻĄāĻŋāĻ•ā§āϞ⧇āϝāĻŧāĻžāϰ⧇āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, āĻĄāĻŦāϞ āĻĄāĻŋāĻ•ā§āϞ⧇āϝāĻŧāĻžāϰ⧇āĻļāύ⧇āϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧀āϝāĻŧāϤāĻž āĻĻā§‚āϰ āĻ•āϰāϤ⧇ āĻāĻŦāĻ‚ āϏāĻ āĻŋāĻ• āϰāĻžāύāϟāĻžāχāĻŽ āĻŦ⧇āĻšā§āϝāĻŋāĻ­āĻŋ⧟āĻžāϰ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰāϤ⧇ āĻ¸ā§āĻŸā§āϝāĻžāϟāĻŋāĻ• āĻŦāĻŋāĻļā§āϞ⧇āώāĻŖ āĻĨ⧇āϕ⧇ āϏāĻŽāϤ⧁āĻ˛ā§āϝ āϰāĻžāύāϟāĻžāχāĻŽ āĻ˜ā§‹āώāĻŖāĻž āĻ¸ā§āĻŦāϝāĻŧāĻ‚āĻ•ā§āϰāĻŋāϝāĻŧāĻ­āĻžāĻŦ⧇ āϤ⧈āϰāĻŋ āĻšāϝāĻŧāĨ¤

    • āĻĄā§‡āĻ­ āĻŽā§‹āĻĄā§‡, āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āϟāĻžāχāĻĒāϗ⧁āϞāĻŋ āĻĨ⧇āϕ⧇ āϏāĻ‚āĻļā§āϞāĻŋāĻˇā§āϟ āϰāĻžāύāϟāĻžāχāĻŽ āĻ­ā§āϝāĻžāϞāĻŋāĻĄā§‡āĻļāύ āχāύāĻĢāĻžāϰ āĻ•āϰāĻžāϰ āĻšā§‡āĻˇā§āϟāĻž āĻ•āϰāĻŦ⧇āĨ¤ āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ āĻāĻ–āĻžāύ⧇ foo: String āχāύāĻĢāĻžāϰāĻĄ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇ foo: string āĻĒā§āϰāĻ•āĻžāϰ āĻĨ⧇āϕ⧇āĨ¤ āϝāĻĻāĻŋ āϟāĻžāχāĻĒāϟāĻŋ āĻāĻ•āϟāĻŋ āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āĻ•āϰāĻž āϟāĻžāχāĻĒ⧇āϰ āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ āĻšāϝāĻŧ, āϤāĻžāĻšāϞ⧇ āχāύāĻĢāĻžāϰāĻĄ āĻ•āϰāĻž āĻĢāϞāĻžāĻĢāϞ āĻšāĻŦ⧇ foo: null (any āϟāĻžāχāĻĒ⧇āϰ āϏāĻŽāĻžāύ) āϝ⧇āĻšā§‡āϤ⧁ āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ⧇āϰ āĻ•āĻžāϛ⧇ āĻāĻ•ā§āϏāϟāĻžāϰāύāĻžāϞ āĻĢāĻžāχāϞ⧇āϰ āϤāĻĨā§āϝ āύ⧇āχāĨ¤

    • āĻĒā§āϰ⧋āĻĄ āĻŽā§‹āĻĄā§‡, āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āĻŦāĻžāĻ¨ā§āĻĄā§‡āϞ⧇āϰ āϏāĻžāχāϜ āĻ•āĻŽāĻžāϤ⧇ āĻ…ā§āϝāĻžāϰ⧇ āĻĢāϰāĻŽā§āϝāĻžāϟ āĻĄāĻŋāĻ•ā§āϞāĻžāϰ⧇āχāĻļāύ āϤ⧈āϰāĻŋ āĻ•āϰāĻŦ⧇ (āĻāĻ–āĻžāύ⧇ āĻĒā§āϰāĻĒāϗ⧁āϞāĻŋ ['foo', 'āĻŦāĻžāϰ'] āĻ āĻ•āĻŽā§āĻĒāĻžāχāϞ āĻ•āϰāĻž āĻšāĻŦ⧇)

  • āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖ 3.2 āĻāĻŦāĻ‚ āύ⧀āĻšā§‡, defineProps()-āĻāϰ āϜāĻ¨ā§āϝ āĻœā§‡āύ⧇āϰāĻŋāĻ• āϟāĻžāχāĻĒ āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāϟāĻžāϰ āĻāĻ•āϟāĻŋ āϞāĻŋāϟāĻžāϰāĻžāϞ āϟāĻžāχāĻĒ āĻŦāĻž āϞ⧋āĻ•āĻžāϞ āχāĻ¨ā§āϟāĻžāϰāĻĢ⧇āϏ⧇āϰ āĻāĻ•āϟāĻŋ āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ⧇āϰ āĻŽāĻ§ā§āϝ⧇ āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧ āĻ›āĻŋāϞāĨ¤

    āĻāχ āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧāϤāĻž 3.3 āĻ āϏāĻŽāĻžāϧāĻžāύ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āĨ¤ Vue-āĻāϰ āϏāĻ°ā§āĻŦāĻļ⧇āώ āϏāĻ‚āĻ¸ā§āĻ•āϰāĻŖāϟāĻŋ āϟāĻžāχāĻĒ āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāϟāĻžāϰ āĻĒāϜāĻŋāĻļāύ⧇ āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āĻ•āϰāĻž āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏāĻŋāĻ‚ āĻāĻŦāĻ‚ āϜāϟāĻŋāϞ āϟāĻžāχāĻĒ⧇āϰ āĻāĻ•āϟāĻŋ āϏ⧀āĻŽāĻŋāϤ āϏ⧇āϟ āϏāĻŽāĻ°ā§āĻĨāύ āĻ•āϰ⧇āĨ¤ āϝāĻžāχāĻšā§‹āĻ•, āϝ⧇āĻšā§‡āϤ⧁ āϰāĻžāύāϟāĻžāχāĻŽ āĻ•āύāĻ­āĻžāϰāĻļ⧇āύ āϧāϰāύāϟāĻŋ āĻāĻ–āύāĻ“ AST-āĻ­āĻŋāĻ¤ā§āϤāĻŋāĻ•, āĻ•āĻŋāϛ⧁ āĻ•āĻŽāĻĒā§āϞ⧇āĻ•ā§āϏ āϟāĻžāχāĻĒ⧇āϰ āĻĒā§āϰāĻ•ā§ƒāϤ āϟāĻžāχāĻĒ āĻ…ā§āϝāĻžāύāĻžāϞāĻžāχāϏāĻŋāϏ āĻĒā§āϰāϝāĻŧā§‹āϜāύ, āϝ⧇āĻŽāύ āĻ•āĻ¨ā§āĻĄāĻŋāĻļāύāĻžāϞ āϟāĻžāχāĻĒ, āϏāĻŽāĻ°ā§āĻĨāĻŋāϤ āύāϝāĻŧāĨ¤ āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ āϏāĻŋāĻ™ā§āϗ⧇āϞ āĻĒā§āϰāĻĒ⧇āϰ āϧāϰāϪ⧇āϰ āϜāĻ¨ā§āϝ āĻļāĻ°ā§āϤāϏāĻžāĻĒ⧇āĻ•ā§āώ āϟāĻžāχāĻĒāϗ⧁āϞāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ, āϤāĻŦ⧇ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻĒā§āϰāĻĒāϏ āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ āύāϝāĻŧāĨ¤

Reactive Props Destructure ​

In Vue 3.5 and above, variables destructured from the return value of defineProps are reactive. Vue's compiler automatically prepends props. when code in the same <script setup> block accesses variables destructured from defineProps:

ts
const { foo } = defineProps(['foo'])

watchEffect(() => {
  // runs only once before 3.5
  // re-runs when the "foo" prop changes in 3.5+
  console.log(foo)
})

The above is compiled to the following equivalent:

js
const props = defineProps(['foo'])

watchEffect(() => {
  // `foo` transformed to `props.foo` by the compiler
  console.log(props.foo)
})

In addition, you can use JavaScript's native default value syntax to declare default values for the props. This is particularly useful when using the type-based props declaration:

ts
interface Props {
  msg?: string
  labels?: string[]
}

const { msg = 'hello', labels = ['one', 'two'] } = defineProps<Props>()

Default props values when using type declaration ​

In 3.5 and above, default values can be naturally declared when using Reactive Props Destructure. But in 3.4 and below, Reactive Props Destructure is not enabled by default. In order to declare props default values with type-based declaration, the withDefaults compiler macro is needed:

ts
interface Props {
  msg?: string
  labels?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  msg: 'hello',
  labels: () => ['one', 'two']
})

āĻāϟāĻŋ āϏāĻŽāϤ⧁āĻ˛ā§āϝ āϰāĻžāύāϟāĻžāχāĻŽ āĻĒā§āϰāĻĒāϏ default āĻ…āĻĒāĻļāύ⧇āϰ āĻ•āĻŽā§āĻĒāĻžāχāϞ āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤ āωāĻĒāϰāĻ¨ā§āϤ⧁, withDefaults āĻšā§‡āĻ˛ā§āĻĒāĻžāϰ āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻ­ā§āϝāĻžāϞ⧁āϗ⧁āϞāĻŋāϰ āϜāĻ¨ā§āϝ āϟāĻžāχāĻĒ āĻšā§‡āĻ• āĻĒā§āϰāĻĻāĻžāύ āĻ•āϰ⧇ āĻāĻŦāĻ‚ āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧇ āϝ⧇ āĻĒā§āϰāĻ¤ā§āϝāĻžāĻŦāĻ°ā§āϤāĻŋāϤ props āϟāĻžāχāĻĒāϟāĻŋāϤ⧇ āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻ­ā§āϝāĻžāϞ⧁ āĻĄāĻŋāĻ•ā§āϞāĻžāϰāĻĄ āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝāϗ⧁āϞāĻŋāϰ āϜāĻ¨ā§āϝ āĻ…āĻĒāĻļāύāĻžāϞ āĻĢā§āĻ˛ā§āϝāĻžāĻ—āϗ⧁āϞāĻŋ āϰāĻŋāĻŽā§āĻ­ āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āĨ¤

INFO

Note that default values for mutable reference types (like arrays or objects) should be wrapped in functions when using withDefaults to avoid accidental modification and external side effects. This ensures each component instance gets its own copy of the default value. This is not necessary when using default values with destructure.

defineModel() ​

  • Only available in 3.4+

āĻāχ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋āϟāĻŋ āĻāĻ•āϟāĻŋ āĻĻā§āĻŦāĻŋ-āĻŽā§āĻ–ā§€ āĻŦāĻžāχāĻ¨ā§āĻĄāĻŋāĻ‚ āĻĒā§āϰāĻĒ āĻ˜ā§‹āώāĻŖāĻž āĻ•āϰāϤ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇ āϝāĻž āĻŽā§‚āϞ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻĨ⧇āϕ⧇ v-model āĻāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āωāĻĻāĻžāĻšāϰāĻŖ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ v-model āĻ—āĻžāχāĻĄā§‡āĻ“ āφāϞ⧋āϚāύāĻž āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇āĨ¤

āĻšā§āĻĄā§‡āϰ āύāĻŋāĻšā§‡, āĻāχ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋ āĻāĻ•āϟāĻŋ āĻŽāĻĄā§‡āϞ āĻĒā§āϰāĻĒ āĻāĻŦāĻ‚ āĻāĻ•āϟāĻŋ āϏāĻ‚āĻļā§āϞāĻŋāĻˇā§āϟ āĻŽāĻžāύ āφāĻĒāĻĄā§‡āϟ āχāϭ⧇āĻ¨ā§āϟ āĻ˜ā§‹āώāĻŖāĻž āĻ•āϰ⧇āĨ¤ āϝāĻĻāĻŋ āĻĒā§āϰāĻĨāĻŽ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟāϟāĻŋ āĻāĻ•āϟāĻŋ āφāĻ•ā§āώāϰāĻŋāĻ• āĻ¸ā§āĻŸā§āϰāĻŋāĻ‚ āĻšāϝāĻŧ āϤāĻŦ⧇ āĻāϟāĻŋ āĻĒā§āϰāĻĒ āύāĻžāĻŽ āĻšāĻŋāϏāĻžāĻŦ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšāĻŦ⧇; āĻ…āĻ¨ā§āϝāĻĨāĻžāϝāĻŧ āĻĒā§āϰāĻĒ āύāĻžāĻŽāϟāĻŋ āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻšāĻŦ⧇ "modelValue"āĨ¤ āωāĻ­āϝāĻŧ āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇āχ, āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ āĻ…āϤāĻŋāϰāĻŋāĻ•ā§āϤ āĻ…āĻŦāĻœā§‡āĻ•ā§āϟāĻ“ āĻĒāĻžāϏ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ āϝāĻž āĻĒā§āϰāĻĒ⧇āϰ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϗ⧁āϞāĻŋ āĻāĻŦāĻ‚ āĻŽāĻĄā§‡āϞ āϰ⧇āĻĢ⧇āϰ āĻŽāĻžāύ āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϗ⧁āϞāĻŋ āĻ…āĻ¨ā§āϤāĻ°ā§āϭ⧁āĻ•ā§āϤ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤

js
// declares "modelValue" prop, consumed by parent via v-model
const model = defineModel()
// OR: declares "modelValue" prop with options
const model = defineModel({ type: String })

// emits "update:modelValue" when mutated
model.value = 'hello'

// declares "count" prop, consumed by parent via v-model:count
const count = defineModel('count')
// OR: declares "count" prop with options
const count = defineModel('count', { type: Number, default: 0 })

function inc() {
  // emits "update:count" when mutated
  count.value++
}

WARNING

āϝāĻĻāĻŋ āφāĻĒāύāĻžāϰ āĻ•āĻžāϛ⧇ defineModel āĻĒā§āϰāĻĒ⧇āϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ default āĻŽāĻžāύ āĻĨāĻžāϕ⧇ āĻāĻŦāĻ‚ āφāĻĒāύāĻŋ āĻāχ āĻĒā§āϰāĻĒ⧇āϰ āϜāĻ¨ā§āϝ āĻ…āĻ­āĻŋāĻ­āĻžāĻŦāĻ• āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻĨ⧇āϕ⧇ āϕ⧋āύ⧋ āĻŽāĻžāύ āĻĒā§āϰāĻĻāĻžāύ āύāĻž āĻ•āϰ⧇āύ, āϤāĻžāĻšāϞ⧇ āĻāϟāĻŋ āĻĒāĻŋāϤāĻžāĻŽāĻžāϤāĻž āĻāĻŦāĻ‚ āĻļāĻŋāĻļ⧁ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋāϰ āĻŽāĻ§ā§āϝ⧇ āĻāĻ•āϟāĻŋ āĻĄāĻŋ-āϏāĻŋāĻ™ā§āĻ•ā§āϰ⧋āύāĻžāχāĻœā§‡āĻļāύ āϏ⧃āĻˇā§āϟāĻŋ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āύ⧀āĻšā§‡āϰ āωāĻĻāĻžāĻšāϰāϪ⧇, āĻĒāĻŋāϤāĻžāĻŽāĻžāϤāĻžāϰ myRef āĻ…āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ, āĻ•āĻŋāĻ¨ā§āϤ⧁ āϏāĻ¨ā§āϤāĻžāύ⧇āϰ model āĻšāϞ 1:

Child.vue
vue
<script setup>
const model = defineModel({ default: 1 })
</script>
Parent.vue
vue
<script setup>
const myRef = ref()
</script>

<template>
  <Child v-model="myRef"></Child>
</template>

Modifiers and Transformers ​

v-model āύāĻŋāĻ°ā§āĻĻ⧇āĻļ⧇āϰ āϏāĻžāĻĨ⧇ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻŽāĻĄāĻŋāĻĢāĻžāϝāĻŧāĻžāϰ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āĻ•āϰāϤ⧇, āφāĻŽāϰāĻž defineModel() āĻāϰ āϰāĻŋāϟāĻžāĻ°ā§āύ āĻŽāĻžāύāϕ⧇ āĻāĻ­āĻžāĻŦ⧇ āĻ§ā§āĻŦāĻ‚āϏ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŋ:

js
const [modelValue, modelModifiers] = defineModel()

// corresponds to v-model.trim
if (modelModifiers.trim) {
  // ...
}

āϝāĻ–āύ āĻāĻ•āϟāĻŋ āϏāĻ‚āĻļā§‹āϧāĻ• āωāĻĒāĻ¸ā§āĻĨāĻŋāϤ āĻĨāĻžāϕ⧇, āϤāĻ–āύ āφāĻŽāĻžāĻĻ⧇āϰ āϏāĻŽā§āĻ­āĻŦāϤ āĻŽāĻžāύāϟāĻŋ āĻĒā§āϝāĻžāϰ⧇āĻ¨ā§āĻŸā§‡āϰ āϏāĻžāĻĨ⧇ āĻĒāĻĄāĻŧāĻžāϰ āĻŦāĻž āϏāĻŋāĻ™ā§āĻ• āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āϰ⧂āĻĒāĻžāĻ¨ā§āϤāϰ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇āĨ¤ āφāĻŽāϰāĻž get āĻāĻŦāĻ‚ set āĻŸā§āϰāĻžāĻ¨ā§āϏāĻĢāϰāĻŽāĻžāϰ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϗ⧁āϞāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻāϟāĻŋ āĻ…āĻ°ā§āϜāύ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŋ:

js
const [modelValue, modelModifiers] = defineModel({
  // get() omitted as it is not needed here
  set(value) {
    // if the .trim modifier is used, return trimmed value
    if (modelModifiers.trim) {
      return value.trim()
    }
    // otherwise, return the value as-is
    return value
  }
})

Usage with TypeScript ​

defineProps āĻāĻŦāĻ‚ defineEmits āĻāϰ āĻŽāϤ⧋, defineModel āĻŽāĻĄā§‡āϞ⧇āϰ āĻŽāĻžāύ āĻāĻŦāĻ‚ āĻŽāĻĄāĻŋāĻĢāĻžāϝāĻŧāĻžāϰ⧇āϰ āϧāϰāύ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ•āϰāϤ⧇ āϟāĻžāχāĻĒ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟāĻ“ āĻĒ⧇āϤ⧇ āĻĒāĻžāϰ⧇:

ts
const modelValue = defineModel<string>()
//    ^? Ref<string | undefined>

// default model with options, required removes possible undefined values
const modelValue = defineModel<string>({ required: true })
//    ^? Ref<string>

const [modelValue, modifiers] = defineModel<string, 'trim' | 'uppercase'>()
//                 ^? Record<'trim' | 'uppercase', true | undefined>

defineExpose() ​

<script setup> āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϗ⧁āϞāĻŋ āĻĄāĻŋāĻĢāĻ˛ā§āϟāϰ⧂āĻĒ⧇ āĻŦāĻ¨ā§āϧ āĻĨāĻžāϕ⧇ - āϝ⧇āĻŽāύ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϰ āϏāĻ°ā§āĻŦāϜāύ⧀āύ āωāĻĻāĻžāĻšāϰāĻŖ, āϝāĻž āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟ āϰ⧇āĻĢ āĻŦāĻž $parent āĻšā§‡āχāύ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻĒ⧁āύāϰ⧁āĻĻā§āϧāĻžāϰ āĻ•āϰāĻž āĻšāϝāĻŧ, āĻĄāĻŋāĻ•ā§āϞāĻžāϰāĻĄ āϕ⧋āύ⧋ āĻŦāĻžāχāĻ¨ā§āĻĄāĻŋāĻ‚ āϕ⧇ āĻĒā§āϰāĻ•āĻžāĻļ āĻ•āϰāĻŦ⧇ āύāĻž <script setup> āĻāϰ āĻ­āĻŋāϤāϰ⧇āĨ¤

āĻāĻ•āϟāĻŋ <script setup> āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡ āĻĒā§āϰ⧋āĻĒāĻžāĻ°ā§āϟāĻŋāϗ⧁āϞāĻŋ āĻ¸ā§āĻĒāĻˇā§āϟāĻ­āĻžāĻŦ⧇ āĻĒā§āϰāĻ•āĻžāĻļ āĻ•āϰāϤ⧇, defineExpose āĻ•āĻŽā§āĻĒāĻžāχāϞāĻžāϰ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ:

vue
<script setup>
import { ref } from 'vue'

const a = 1
const b = ref(2)

defineExpose({
  a,
  b
})
</script>

āϝāĻ–āύ āĻāĻ•āϟāĻŋ āĻĒā§āϝāĻžāϰ⧇āĻ¨ā§āϟ āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟ āϰ⧇āĻĢ⧇āϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻāχ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟāϟāĻŋāϰ āĻāĻ•āϟāĻŋ āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ āĻĒāĻžāύ, āϤāĻ–āύ āĻĒ⧁āύāϰ⧁āĻĻā§āϧāĻžāϰāĻ•ā§ƒāϤ āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ { a: number, b: number } āφāĻ•āĻžāϰ⧇āϰ āĻšāĻŦ⧇ (āϰ⧇āĻĢāϗ⧁āϞāĻŋ āĻ¸ā§āĻŦāϝāĻŧāĻ‚āĻ•ā§āϰāĻŋāϝāĻŧāĻ­āĻžāĻŦ⧇ āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ• āωāĻĻāĻžāĻšāϰāϪ⧇āϰ āĻŽāϤ⧋āχ unwrapped āĻšāϝāĻŧ)āĨ¤

defineOptions() ​

  • āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ ā§Š.ā§Š+ āĻ āϏāĻŽāĻ°ā§āĻĨāĻŋāϤ

āĻāχ āĻŽā§āϝāĻžāĻ•ā§āϰ⧋āϟāĻŋ āĻāĻ•āϟāĻŋ āĻĒ⧃āĻĨāĻ• <script> āĻŦā§āϞāĻ• āĻŦā§āϝāĻŦāĻšāĻžāϰ āύāĻž āĻ•āϰ⧇ āϏāϰāĻžāϏāϰāĻŋ <script setup> āĻāϰ āĻ­āĻŋāϤāϰ⧇ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻ…āĻĒāĻļāύ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻ•āϰāϤ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇:

vue
<script setup>
defineOptions({
  inheritAttrs: false,
  customOptions: {
    /* ... */
  }
})
</script>
  • This is a macro. The options will be hoisted to module scope and cannot access local variables in <script setup> that are not literal constants.

defineSlots() ​

  • āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ ā§Š.ā§Š+ āĻ āϏāĻŽāĻ°ā§āĻĨāĻŋāϤ

This macro can be used to provide type hints to IDEs for slot name and props type checking.

defineSlots() āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āĻāĻ•āϟāĻŋ āϟāĻžāχāĻĒ āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāϟāĻžāϰ āϰāĻŋāϏāĻŋāĻ­ āĻ•āϰ⧇ āĻāĻŦāĻ‚ āϕ⧋āύ⧋ āϰāĻžāύāϟāĻžāχāĻŽ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āύ⧇āχāĨ¤ āϟāĻžāχāĻĒ āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāϟāĻžāϰ āĻāĻ•āϟāĻŋ āϟāĻžāχāĻĒ āϞāĻŋāϟāĻžāϰāĻžāϞ āĻšāĻ“āϝāĻŧāĻž āωāϚāĻŋāϤ āϝ⧇āĻ–āĻžāύ⧇ āĻĒā§āϰ⧋āĻĒāĻžāĻ°ā§āϟāĻŋ āϕ⧀-āϟāĻŋ āĻ¸ā§āϞāĻŸā§‡āϰ āύāĻžāĻŽ āĻāĻŦāĻ‚ āĻ­ā§āϝāĻžāϞ⧁āϰ āϟāĻžāχāĻĒāϟāĻŋ āĻ¸ā§āϞāϟ āĻĢāĻžāĻ‚āĻļāύāĨ¤ āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āĻĒā§āϰāĻĨāĻŽ āφāĻ°ā§āϗ⧁āĻŽā§‡āĻ¨ā§āϟ āĻšāϞ āĻĒā§āϰāĻĒāϏ āϝāĻž āĻ¸ā§āϞāϟ āĻĒāĻžāĻ“āϝāĻŧāĻžāϰ āφāĻļāĻž āĻ•āϰ⧇ āĻāĻŦāĻ‚ āĻāϰ āϟāĻžāχāĻĒāϟāĻŋ āĻŸā§‡āĻŽāĻĒā§āϞ⧇āĻŸā§‡āϰ āĻ¸ā§āϞāϟ āĻĒā§āϰāĻĒāϏ⧇āϰ āϜāĻ¨ā§āϝ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤ āϰāĻŋāϟāĻžāĻ°ā§āύ⧇āϰ āϟāĻžāχāĻĒāϟāĻŋ āĻŦāĻ°ā§āϤāĻŽāĻžāύ⧇ āωāĻĒ⧇āĻ•ā§āώāĻž āĻ•āϰāĻž āĻšāϝāĻŧ⧇āϛ⧇ āĻāĻŦāĻ‚ āĻāϟāĻŋ any āĻšāϤ⧇ āĻĒāĻžāϰ⧇, āϤāĻŦ⧇ āφāĻŽāϰāĻž āĻ­āĻŦāĻŋāĻˇā§āϝāϤ⧇ āĻ¸ā§āϞāϟ āϏāĻžāĻŽāĻ—ā§āϰ⧀ āĻšā§‡āĻ• āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻāϟāĻŋāϰ āϏ⧁āĻŦāĻŋāϧāĻž āύāĻŋāϤ⧇ āĻĒāĻžāϰāĻŋāĨ¤

āĻāϟāĻŋ slots āĻ…āĻŦāĻœā§‡āĻ•ā§āϟāĻ“ āϰāĻŋāϟāĻžāĻ°ā§āύ āĻĻ⧇āϝāĻŧ, āϝāĻž āϏ⧇āϟāφāĻĒ āĻĒā§āϰāϏāĻ™ā§āϗ⧇ āĻĒā§āϰāĻ•āĻžāĻļāĻŋāϤ slots āĻ…āĻŦāĻœā§‡āĻ•ā§āĻŸā§‡āϰ āϏāĻŽāϤ⧁āĻ˛ā§āϝ āĻ…āĻĨāĻŦāĻž useSlots() āĻĻā§āĻŦāĻžāϰāĻž āϰāĻŋāϟāĻžāĻ°ā§āύāĻĄ āĻšāϝāĻŧāĨ¤

vue
<script setup lang="ts">
const slots = defineSlots<{
  default(props: { msg: string }): any
}>()
</script>

useSlots() & useAttrs() ​

<script setup>-āĻāϰ āĻ­āĻŋāϤāϰ⧇ slots āĻāĻŦāĻ‚ attrs-āĻāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āϤ⧁āϞāύāĻžāĻŽā§‚āϞāĻ•āĻ­āĻžāĻŦ⧇ āĻŦāĻŋāϰāϞ āĻšāĻ“āϝāĻŧāĻž āωāϚāĻŋāϤ, āĻ•āĻžāϰāĻŖ āφāĻĒāύāĻŋ āĻŸā§‡āĻŽāĻĒā§āϞ⧇āĻŸā§‡ $slots āĻāĻŦāĻ‚ $attrs āĻšāĻŋāϏ⧇āĻŦ⧇ āϏāϰāĻžāϏāϰāĻŋ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇āύāĨ¤ āĻŦāĻŋāϰāϞ āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇ āϝ⧇āĻ–āĻžāύ⧇ āφāĻĒāύāĻžāϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ āĻšāϝāĻŧ, āϝāĻĨāĻžāĻ•ā§āϰāĻŽā§‡ useSlots āĻāĻŦāĻ‚ useAttrs āĻšā§‡āĻ˛ā§āĻĒāĻžāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ:

vue
<script setup>
import { useSlots, useAttrs } from 'vue'

const slots = useSlots()
const attrs = useAttrs()
</script>

useSlots āĻāĻŦāĻ‚ useAttrs āĻšāϞ āĻĒā§āϰāĻ•ā§ƒāϤ āϰāĻžāύāϟāĻžāχāĻŽ āĻĢāĻžāĻ‚āĻļāύ āϝāĻž setupContext.slots āĻāĻŦāĻ‚ setupContext.attrs āĻāϰ āϏāĻŽāϤ⧁āĻ˛ā§āϝ āϰāĻŋāϟāĻžāĻ°ā§āύ āĻ•āϰ⧇āĨ¤ āĻāϗ⧁āϞāĻŋ āϏāĻžāϧāĻžāϰāĻŖ āĻ•āĻŽā§āĻĒā§‹āϜāĻŋāĻļāύ API āĻĢāĻžāĻ‚āĻļāύ⧇āĻ“ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤

Usage alongside normal <script> ​

<script setup> āϏāĻžāϧāĻžāϰāĻŖ <script> āĻāϰ āϏāĻžāĻĨ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āĻāĻ•āϟāĻŋ āύāϰāĻŽāĻžāϞ <script> āĻĒā§āϰāϝāĻŧā§‹āϜāύ āĻšāϤ⧇ āĻĒāĻžāϰ⧇ āϝ⧇āχ āĻ•ā§āώ⧇āĻ¤ā§āϰ⧇ āφāĻŽāĻžāĻĻ⧇āϰ āĻĒā§āϰāϝāĻŧā§‹āϜāύ:

  • āϝ⧇ āĻ…āĻĒāĻļāύāϗ⧁āϞāĻŋ <script setup>-āĻ āĻĒā§āϰāĻ•āĻžāĻļ āĻ•āϰāĻž āϝāĻžāϝāĻŧ āύāĻž āϏ⧇āϗ⧁āϞāĻŋ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻ•āϰ⧁āύ, āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ inheritAttrs āĻŦāĻž āĻĒā§āϞāĻžāĻ—āχāύāϗ⧁āϞāĻŋāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻāύāĻžāĻŦāϞ āĻ•āϰāĻž āĻ•āĻžāĻ¸ā§āϟāĻŽ āĻ…āĻĒāĻļāύāϗ⧁āϞāĻŋ (3.3-āĻ [defineOptions](/api/sfc-script-setup#defineoptions āĻĻā§āĻŦāĻžāϰāĻž āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāĻŋāϤ āĻšāϤ⧇ āĻĒāĻžāϰ⧇) +)āĨ¤
  • āύ⧇āχāĻŽāĻĄ āĻāĻ•ā§āϏāĻĒā§‹āĻ°ā§āϟ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻ•āϰāĻžāĨ¤
  • āϏāĻžāχāĻĄ āχāĻĢ⧇āĻ•ā§āϟ āϚāĻžāϞāĻžāύ āĻŦāĻž āĻāĻŽāύ āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ āϝāĻž āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āĻāĻ•āĻŦāĻžāϰ āĻāĻ•ā§āϏāĻŋāĻ•āĻŋāωāϟ āĻ•āϰāĻž āωāϚāĻŋāϤāĨ¤
vue
<script>
// normal <script>, executed in module scope (only once)
runSideEffectOnce()

// declare additional options
export default {
  inheritAttrs: false,
  customOptions: {}
}
</script>

<script setup>
// executed in setup() scope (for each instance)
</script>

āĻāĻ•āχ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡ <script setup> āĻāĻŦāĻ‚ <script> āĻāĻ•āĻ¤ā§āϰāĻŋāϤ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āϏāĻžāĻĒā§‹āĻ°ā§āĻŸā§‡āĻĄ, āωāĻĒāϰ⧇ āĻŦāĻ°ā§āĻŖāĻŋāϤ āĻĒāϰāĻŋāĻ¸ā§āĻĨāĻŋāϤāĻŋāϤ⧇ āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧāĨ¤ āĻŦāĻŋāĻļ⧇āώāĻ­āĻžāĻŦ⧇:

  • NOT āĻ…āĻĒāĻļāύāϗ⧁āϞāĻŋāϰ āϜāĻ¨ā§āϝ āĻāĻ•āϟāĻŋ āĻĒ⧃āĻĨāĻ• <script> āϏ⧇āĻ•āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇āύ āύāĻž āϝāĻž <script setup> āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āχāϤāĻŋāĻŽāĻ§ā§āϝ⧇āχ āĻĄāĻŋāĻĢāĻžāχāύāĻĄ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇, āϝ⧇āĻŽāύ props āĻāĻŦāĻ‚ emitsāĨ¤
  • <script setup>-āĻāϰ āĻŽāĻ§ā§āϝ⧇ āϤ⧈āϰāĻŋ āϭ⧇āϰāĻŋāϝāĻŧ⧇āĻŦāϞāϗ⧁āϞāĻŋāϕ⧇ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ⧇ āĻĒā§āϰāĻĒāĻžāĻ°ā§āϟāĻŋ āĻšāĻŋāϏ⧇āĻŦ⧇ āϝ⧋āĻ— āĻ•āϰāĻž āĻšāϝāĻŧ āύāĻž, āϝāĻž āĻ…āĻĒāĻļāύ āĻāĻĒāĻŋāφāχ āĻĨ⧇āϕ⧇ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏāϝ⧋āĻ—ā§āϝ āĻ•āϰ⧇ āϤ⧋āϞ⧇āĨ¤ āĻāχāĻ­āĻžāĻŦ⧇ Mixing API āϗ⧁āϞāĻŋāϕ⧇ āĻĻ⧃āĻĸāĻŧāĻ­āĻžāĻŦ⧇ āύāĻŋāĻ°ā§ā§ŽāϏāĻžāĻšāĻŋāϤ āĻ•āϰāĻž āĻšāϝāĻŧ⧎

āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āϏāĻžāĻĒā§‹āĻ°ā§āĻŸā§‡āĻĄ āύāϝāĻŧ āĻāĻŽāύ āĻĒāϰāĻŋāĻ¸ā§āĻĨāĻŋāϤāĻŋāϤ⧇ āύāĻŋāĻœā§‡āϕ⧇ āϖ⧁āρāĻœā§‡ āĻĒāĻžāύ āϤāĻžāĻšāϞ⧇ <script setup> āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤ⧇ āφāĻĒāύāĻžāϰ āĻāĻ•āϟāĻŋ āĻ¸ā§āĻĒāĻˇā§āϟ setup() āĻĢāĻžāĻ‚āĻļāύ⧇ āĻ¸ā§āϝ⧁āχāϚ āĻ•āϰāĻžāϰ āĻ•āĻĨāĻž āĻŦāĻŋāĻŦ⧇āϚāύāĻž āĻ•āϰāĻž āωāϚāĻŋāϤāĨ¤

Top-level await ​

āϟāĻĒ-āϞ⧇āϭ⧇āϞ await āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇ <script setup> āĻāϰ āĻŽāĻ§ā§āϝ⧇āĨ¤ āĻĢāϞāĻ¸ā§āĻŦāϰ⧂āĻĒ āϕ⧋āĻĄāϟāĻŋ async setup() āĻšāĻŋāϏāĻžāĻŦ⧇ āĻ•āĻŽā§āĻĒāĻžāχāϞ āĻ•āϰāĻž āĻšāĻŦ⧇:

vue
<script setup>
const post = await fetch(`/api/post/1`).then((r) => r.json())
</script>

āωāĻĒāϰāĻ¨ā§āϤ⧁, āĻĒā§āϰāϤ⧀āĻ•ā§āώāĻŋāϤ āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύāϟāĻŋ āĻ¸ā§āĻŦāϝāĻŧāĻ‚āĻ•ā§āϰāĻŋāϝāĻŧāĻ­āĻžāĻŦ⧇ āĻāĻ•āϟāĻŋ āĻĢāϰāĻŽā§āϝāĻžāĻŸā§‡ āϏāĻ‚āĻ•āϞāĻŋāϤ āĻšāĻŦ⧇ āϝāĻž await āĻāϰ āĻĒāϰ⧇ āĻ•āĻžāϰ⧇āĻ¨ā§āϟ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āωāĻĻāĻžāĻšāϰāϪ⧇āϰ āĻ•āύāĻŸā§‡āĻ•ā§āϏ āϏāĻ‚āϰāĻ•ā§āώāĻŖ āĻ•āϰ⧇āĨ¤

āύ⧋āϟ

async setup() āĻāϰ āϏāĻžāĻĨ⧇ Suspense āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇, āϝāĻž āĻāĻ–āύāĻ“ āĻĒāϰ⧀āĻ•ā§āώāĻžāĻŽā§‚āϞāĻ• āĻŦ⧈āĻļāĻŋāĻˇā§āĻŸā§āϝāĨ¤ āφāĻŽāϰāĻž āĻĒāϰāĻŦāĻ°ā§āϤ⧀ āϰāĻŋāϞāĻŋāĻœā§‡ āĻāϟāĻŋ āĻšā§‚āĻĄāĻŧāĻžāĻ¨ā§āϤ āĻ•āϰāĻžāϰ āĻāĻŦāĻ‚ āĻĄāϕ⧁āĻŽā§‡āĻ¨ā§āϟ āĻ•āϰāĻžāϰ āĻĒāϰāĻŋāĻ•āĻ˛ā§āĻĒāύāĻž āĻ•āϰāĻ›āĻŋāĨ¤ āϤāĻŦ⧇, āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āĻāĻ–āύāχ āϜāĻžāύāϤ⧇ āφāĻ—ā§āϰāĻšā§€ āĻšāύ, āϤāĻžāĻšāϞ⧇ āφāĻĒāύāĻŋ āĻāϰ āĻĒāϰ⧀āĻ•ā§āώāĻž āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤

Import Statements ​

āĻ­āĻŋāωāϤ⧇ āĻŦāĻŋāĻŦ⧃āϤāĻŋ āχāĻŽā§āĻĒā§‹āĻ°ā§āϟ āĻ•āϰ⧁āύ ECMAScript āĻŽāĻĄāĻŋāωāϞ āĻ¸ā§āĻĒ⧇āϏāĻŋāĻĢāĻŋāϕ⧇āĻļāύāĨ¤ āωāĻĒāϰāĻ¨ā§āϤ⧁, āφāĻĒāύāĻŋ āφāĻĒāύāĻžāϰ āĻŦāĻŋāĻ˛ā§āĻĄ āϟ⧁āϞ āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ⧇āĻļāύ⧇ āϏāĻ‚āĻœā§āĻžāĻžāϝāĻŧāĻŋāϤ āωāĻĒāύāĻžāĻŽ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ:

vue
<script setup>
import { ref } from 'vue'
import { componentA } from './Components'
import { componentB } from '@/Components'
import { componentC } from '~/Components'
</script>

Generics ​

āĻœā§‡āύ⧇āϰāĻŋāĻ• āϟāĻžāχāĻĒ āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāϟāĻžāϰāϗ⧁āϞāĻŋ <script> āĻŸā§āϝāĻžāϗ⧇ generic āĻ…ā§āϝāĻžāĻŸā§āϰāĻŋāĻŦāĻŋāωāϟ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āĻĄāĻŋāĻ•ā§āĻ˛ā§‡ā§ŸāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇:

vue
<script setup lang="ts" generic="T">
defineProps<{
  items: T[]
  selected: T
}>()
</script>

āϟāĻžāχāĻĒāĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āĻŸā§‡ <...>-āĻāϰ āĻŽāĻ§ā§āϝ⧇ āĻĒā§āϝāĻžāϰāĻžāĻŽāĻŋāϟāĻžāϰ āϞāĻŋāĻ¸ā§āĻŸā§‡āϰ āĻŽāϤ⧋āχ generic-āĻāϰ āĻ­ā§āϝāĻžāϞ⧁ āĻ āĻŋāĻ• āĻāĻ•āχāĻ­āĻžāĻŦ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤ āωāĻĻāĻžāĻšāϰāĻŖāĻ¸ā§āĻŦāϰ⧂āĻĒ, āφāĻĒāύāĻŋ āĻāĻ•āĻžāϧāĻŋāĻ• āĻĒā§āϝāϰāĻžāĻŽāĻŋāϟāĻžāϰ, extends āϏ⧀āĻŽāĻžāĻŦāĻĻā§āϧāϤāĻž, āĻĄāĻŋāĻĢāĻ˛ā§āϟ āϟāĻžāχāĻĒāϏ āĻāĻŦāĻ‚ āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ āχāĻŽā§āĻĒā§‹āĻ°ā§āĻŸā§‡āĻĄ āĻ•āϰāĻž āϟāĻžāχāĻĒāϗ⧁āϞāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ:

vue
<script
  setup
  lang="ts"
  generic="T extends string | number, U extends Item"
>
import type { Item } from './types'
defineProps<{
  id: T
  list: U[]
}>()
</script>

āϝāĻ–āύ āϟāĻžāχāĻĒāϟāĻŋ āĻ…āύ⧁āĻŽāĻžāύ āĻ•āϰāĻž āϝāĻžāϝāĻŧ āύāĻž, āϤāĻ–āύ āĻ¸ā§āĻĒāĻˇā§āϟ āĻĒā§āϰāĻ•āĻžāϰ⧇ āĻĒāĻžāϏ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āφāĻĒāύāĻŋ @vue-generic āύāĻŋāĻ°ā§āĻĻ⧇āĻļāĻŋāĻ•āĻžāϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ:

vue
<template>
  <!-- @vue-generic {import('@/api').Actor} -->
  <ApiSelect v-model="peopleIds" endpoint="/api/actors" id-prop="actorId" />

  <!-- @vue-generic {import('@/api').Genre} -->
  <ApiSelect v-model="genreIds" endpoint="/api/genres" id-prop="genreId" />
</template>

ref-āĻ āĻāĻ•āϟāĻŋ āĻœā§‡āύ⧇āϰāĻŋāĻ• āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āĻŸā§‡āϰ āϰ⧇āĻĢāĻžāϰ⧇āĻ¨ā§āϏ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āφāĻĒāύāĻžāϕ⧇ vue-component-type-helpers āϞāĻžāχāĻŦā§āϰ⧇āϰāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻšāĻŦ⧇ āĻ•āĻžāϰāĻŖ InstanceType āĻ•āĻžāϜ āĻ•āϰāĻŦ⧇ āύāĻžāĨ¤

vue
<script
  setup
  lang="ts"
>
import componentWithoutGenerics from '../component-without-generics.vue';
import genericComponent from '../generic-component.vue';

import type { ComponentExposed } from 'vue-component-type-helpers';

// Works for a component without generics
ref<InstanceType<typeof componentWithoutGenerics>>();

ref<ComponentExposed<typeof genericComponent>>();

Restrictions ​

  • āĻŽāĻĄāĻŋāωāϞ āĻāĻ•ā§āϏāĻŋāĻ•āĻŋāωāĻļāύ āĻļāĻŦā§āĻĻāĻžāĻ°ā§āĻĨāĻŦāĻŋāĻĻā§āϝāĻžāϰ āĻĒāĻžāĻ°ā§āĻĨāĻ•ā§āϝ⧇āϰ āĻ•āĻžāϰāϪ⧇, <script setup> āĻāϰ āĻ­āĻŋāϤāϰ⧇āϰ āϕ⧋āĻĄ āĻāĻ•āϟāĻŋ SFC-āĻāϰ āĻĒā§āϰāϏāĻ™ā§āϗ⧇ āύāĻŋāĻ°ā§āĻ­āϰ āĻ•āϰ⧇āĨ¤ āĻŦāĻžāĻšā§āϝāĻŋāĻ• .js āĻŦāĻž .ts āĻĢāĻžāχāϞ⧇ āϏāϰāĻžāύ⧋ āĻšāϞ⧇, āĻāϟāĻŋ āĻĄā§‡āϭ⧇āϞāĻĒāĻžāϰ āĻāĻŦāĻ‚ āϟ⧁āϞ āωāĻ­āϝāĻŧ⧇āϰ āϜāĻ¨ā§āϝāχ āĻŦāĻŋāĻ­ā§āϰāĻžāĻ¨ā§āϤāĻŋāϰ āĻ•āĻžāϰāĻŖ āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āĻ…āϤāĻāĻŦ, <script setup> src āĻ…ā§āϝāĻžāĻŸā§āϰāĻŋāĻŦāĻŋāωāĻŸā§‡āϰ āϏāĻžāĻĨ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžāĻŦ⧇ āύāĻžāĨ¤
  • <script setup> āχāύ-āĻĄā§‹āĻŽ āϰ⧁āϟ āĻ•āĻŽā§āĻĒā§‹āύ⧇āĻ¨ā§āϟ āĻŸā§‡āĻŽāĻĒā§āϞ⧇āϟ āϏāĻŽāĻ°ā§āĻĨāύ āĻ•āϰ⧇ āύāĻžāĨ¤(āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āφāϞ⧋āϚāύāĻž)
<script setup> has loaded