Single file component in vue3 <script setup> details explanation
- 1. Advantages of common script syntax
- 2. Basic grammar
- 3. Responsive
- 4. Use components
- 5. Use custom commands
- 6. defineProps and defineEmits
- 7. defineExpose
- 8. useSlots and useAttrs
- 9. Top level await
1. Advantages of common script syntax
<script setup>
YesSingle File Component (SFC)
middleUsing a combination API
Compilation timeSyntactic sugar
. Compared withNormal <script> syntax
, it has more advantages
- 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
<script> on the code block
<script setup>
console.log('hello script setup')
</script>
- The code inside will
The contents of the component setup() function are compiled
. This means with ordinary<script>
Only in componentsFirst introduced
WhenExecute once
different,<script setup>
The code inevery time
Component instanceCreated
When executed.
Top-level bindings will be exposed to the template
- When using
<script setup>
Whenever, any<script setup> declared top-level binding
(including variables, function declarations, and what import is introduced) can all betemplate
middleUse directly
<script setup>
// Variable
const msg = 'Hello!'
// Function
function log() {
console.log(msg)
}
</script>
<template>
<div @click="log">{{ msg }}</div>
</template>
- Imported content will be exposed in the same way. mean
You can use the imported helper function directly in template expressions
, 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 state requires
Use responsive APIs explicitly to create
. Just like returning a value from the setup() function, when the ref value is used in the templateWill unpack automatically
:
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
4. Use components
-
<script setup>
Values in the range can also be used directly as the label 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,
Use dynamic components in <script setup>
When you are, you should use dynamic:is
Come 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 be used in its template
<FooBar/>
Quote it yourself. - 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
- Component markers with dots can be used, e.g.
<>
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>
<Form.Input>
<Form.Label>label</Form.Label>
</Form.Input>
</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 attention:
Local custom directives must be named in the form of vNameOfDirective
so that they canUse directly in templates
<script setup>
const vMyDirective = {
beforeMount: (el) => {
// Do some operations on the element
}
}
</script>
<template>
<h1 v-my-directive>This is a Heading</h1>
</template>
<script setup>
// The imported directive can also work and can be renamed to comply with the naming specification.
import { myDirective as vMyDirective } from './'
</script>
6. defineProps and defineEmits
- exist
<script setup>
middlemust
usedefineProps
anddefineEmits
The API comesDeclare props and emits
, they have complete type inference andIt is directly available in <script setup>
<script setup>
const props = defineProps({
foo: String
})
const emit = defineEmits(['change', 'delete'])
// setup code
</script>
-
defineProps
anddefineEmits
AllCompiler macros that can only be used in <script setup>
. themNo import required
And willCompiled 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, the public instance of the component obtained through the template ref or $parent chain,No bindings declared in <script setup> will be exposed
。 - for
In the <script setup> component, explicitly expose the properties to be exposed
, use 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
- exist
<script setup>
useslots
andattrs
It should be very rare becauseAccess them through $slots and $attrs in the template
. In rare scenarios where you do need to use them, you can use them separatelyuseSlots
anduseAttrs
Two helper functions
<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 => r.json())
</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.