SoFunction
Updated on 2025-04-11

vue3 mid-single file component

1. Advantages of common script syntax

<script setup> is a compile-time syntax sugar using a combination API in a single file component (SFC). It has more advantages than the ordinary <script> syntax

  • Less boilerplate content, cleaner code
  • Ability to declare props and throw events using pure Typescript.
  • Better runtime performance (its templates are compiled into rendering functions with the same scope as it, without any intermediate proxy).
  • Better IDE type inference performance (reduces the work of language servers to extract types from code).

2. Basic grammar

To use this syntax, you need to add the setup attribute to the <script> code block

<script setup>
    ('hello script setup')
</script>

The code inside will be compiled into the contents of the component setup() function. This means that unlike the normal <script> that is executed only once when the component is first introduced, the code in <script setup> is executed every time the component instance is created.

Top-level bindings will be exposed to the template

When using <script setup>, any bindings at the top level of the <script setup> declaration (including variables, function declarations, and import content) can be used directly in the template

&lt;script setup&gt;
// Variableconst msg = 'Hello!'

// Functionfunction log() {
  (msg)
}
&lt;/script&gt;

&lt;template&gt;
  &lt;div @click="log"&gt;{{ msg }}&lt;/div&gt;
&lt;/template&gt;

Imported content will be exposed in the same way. It means that the imported helper function can be used directly in template expressions, and it does not need to be exposed through the methods option:

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

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

3. Responsive

Responsive states need to be created explicitly using responsive APIs. Just like returning values ​​from the setup() function, the ref value will be automatically unpacked when used in the template:

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

const count = ref(0)
</script>

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

4. Use components

Values ​​in the <script setup> range can also be used directly as the tag name of the custom component:

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

<template>
  <MyComponent />
</template>

Dynamic Components

Since the component is referenced as a variable rather than as a string key to register, when using a dynamic component in <script setup>, the dynamic:is should be used to bind

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

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

Recursive components

  • A single file component can be referenced by its file name. For example: a component named , can reference itself with <FooBar/> in its template.
  • Please note that this method has lower priority than import components imported. If a named import and component inferred name conflict, you can use the import alias to import:
import { FooBar as FooBarChild } from './components'

Namespace components

  • Pointed component tags, such as <>, can be used to refer to components nested in object properties. This is useful when you need to import multiple components from a single file:
<script setup>
import * as Form from './form-components'
</script>

<template>
  <>
    <>label</>
  </>
</template>

5. Use custom commands

  • Custom directives for global registration will work in a way that is expected, and locally registered directives can be used directly in the template, just like the components mentioned above.
  • But here is a limitation that needs to be noted: local custom directives must be named in the form of vNameOfDirective so that they can be used directly in the template
&lt;script setup&gt;
const vMyDirective = {
  beforeMount: (el) =&gt; {
    // Do some operations on the element  }
}
&lt;/script&gt;
&lt;template&gt;
  &lt;h1 v-my-directive&gt;This is a Heading&lt;/h1&gt;
&lt;/template&gt;
&lt;script setup&gt;
  // The imported directive can also work and can be renamed to comply with the naming specification.  import { myDirective as vMyDirective } from './'
&lt;/script&gt;

6. defineProps and defineEmits

Props and defineEmits APIs must be used in the <script setup> to declare props and emits , which have complete type inference and are directly available in the <script setup>

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

const emit = defineEmits(['change', 'delete'])
// setup code
</script>
  • defineProps and defineEmits are compiler macros that can only be used in <script setup>. They do not need to be imported and will be compiled with the <script setup> processing process.
  • defineProps receives the same value as the props option, and defineEmits also receives the same value as the emits option
  • defineProps and defineEmits are provided with appropriate type inference after the option is passed in.
  • The options passed to defineProps and defineEmits will be promoted from the setup to the scope of the module. Therefore, the passed option cannot refer to local variables declared in the setup scope. Doing so will cause a compilation error. However, it can reference imported bindings, as they are also within module scope

7. defineExpose

  • Components using <script setup> are closed by default, that is, public instances of components obtained through template ref or $parent chains will not expose any bindings declared in <script setup>.
  • To clarify the properties to be exposed in the <script setup> component, use the defineExpose compiler macro
<script setup>
import { ref } from 'vue'

const a = 1
const b = ref(2)

defineExpose({
  a,
  b
})
</script>
  • When the parent component gets the current component instance through the template ref, the obtained instance will be like this { a: number, b: number } (ref will be automatically unpacked just like in normal instances)

8. useSlots and useAttrs

  • It should be rare to use slots and attrs in <script setup>, as they can be accessed through $slots and $attrs in the template. In rare scenarios where you really need to use them, you can useSlots and useAttrs respectively
<script setup>
import { useSlots, useAttrs } from 'vue'

const slots = useSlots()
const attrs = useAttrs()
</script>
  • useSlots and useAttrs are real runtime functions that return values ​​equivalent to and can also be used in ordinary combination APIs.

9. Top level await

The top-level await can be used in <script setup>. The result code will be compiled into async setup()

<script setup>
const post = await fetch(`/api/post/1`).then(r => ())
</script>
  • In addition, the expression of await will be automatically compiled to keep the current component instance context after await
  • Note that async setup() must be used in combination with Suspense, which is currently in the experimental stage.

Appendix: The main differences between <script setup> and <script>

  • performance
    <script setup> has better runtime performance because it compiles templates into rendering methods with the same scope without intermediate proxy. <script> Use the intermediate proxy to compile the template.
  • Code Syntax
    In the <script> block, we need to export the module with boilerplate code. <script setup> allows us to define components without exporting anything. In the <script setup> block, we can get cleaner code with fewer boilerplate files.
  • Execution process
    The <script> block is executed when we first import the component. The <script setup> block will be executed each time the component instance is created.
  • Organize code
    We can organize the code based on the business logic in the <script setup> block. Using <script> blocks is not possible, because we have to follow the encoding structure of Vue's option API or combination API.

Summarize

This is the article about the detailed explanation of single file components &lt;script setup&gt; in vue3 mid-level single file components &lt;script setup&gt;. For more related contents of single file components &lt;script setup&gt;, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!