The execution timing of the setup function
Execution Timing of the setup Function
The setup
function is the core of Vue 3's Composition API and plays a critical role in the component instance creation process. Understanding its execution timing is essential for mastering the component lifecycle and the workings of the reactive system.
Component Initialization Phase
The setup
function is executed during the component instantiation process, specifically triggered when the setupComponent
function is called. This phase occurs before template compilation and DOM mounting and serves as the entry point for the Composition API.
// Pseudocode illustrating the component initialization flow
function mountComponent(vnode, container) {
const instance = createComponentInstance(vnode)
setupComponent(instance) // Here, the setup function is called
setupRenderEffect(instance, container)
}
Inside setupComponent
, the following key steps occur:
- Initialize props and slots
- Execute the
setup
function - Process the results returned by
setup
Comparison with Options API Lifecycle
Compared to Vue 2's Options API, the execution timing of the setup
function is equivalent to the period between beforeCreate
and created
:
// Options API lifecycle order
beforeCreate() {
// The component instance is just created; data observation/events are not initialized yet
},
created() {
// Data observation is complete, but the DOM is not mounted yet
}
// Composition API equivalent behavior
setup() {
// Equivalent to the phase between beforeCreate and created
onBeforeCreate(() => { /*...*/ })
onCreated(() => { /*...*/ })
}
Execution Context Environment
When the setup
function executes, the component instance is partially initialized, but certain features are not fully ready:
setup(props, context) {
// At this point, the following are accessible:
// - props (already made reactive)
// - context containing attrs/slots/emit
// But the following are unavailable:
// - this (not bound to the component instance)
// - template refs (DOM not yet created)
// - child components (not mounted)
}
Establishment of the Reactive System
The setup
function is the primary place for declaring reactive state, and its execution timing ensures the reactive system is initialized before rendering:
setup() {
const count = ref(0) // Reactive declaration
// This effect will be collected after setup completes
watchEffect(() => {
console.log('count changed:', count.value)
})
return { count }
}
Special Handling for Async Components
For async components, the execution timing of the setup
function is delayed until the component finishes loading:
const AsyncComponent = defineAsyncComponent(() =>
import('./AsyncComponent.vue')
)
// Actual execution timing:
// 1. Loading starts when the parent component mounts
// 2. The setup function executes after resources are loaded
// 3. The rendering process then continues
Relationship with the Render Function
After the setup
function completes, its return value is used for the execution of the render function:
setup() {
const msg = ref('Hello')
// This return value will be injected into the render context
return {
msg
}
}
// The compiled render function can access the setup return value
function render(_ctx) {
return h('div', _ctx.msg)
}
Server-Side Rendering Scenario
In SSR environments, the execution timing of the setup
function receives special handling:
// Server-side execution flow:
// 1. Create the component instance
// 2. Synchronously execute setup
// 3. Execute render to generate a string
// During client-side hydration:
// 1. Reuse server-side state
// 2. The setup function is not executed again
// 3. Proceed directly to DOM patching
Error Handling Timing
Synchronous errors inside the setup
function are caught immediately, while asynchronous errors require additional handling:
setup() {
// Synchronous errors - caught by Vue's error handler
const value = riskyOperation()
// Asynchronous errors - require manual .catch
fetchData().catch(err => {
// Must be handled manually
})
}
Cases of Multiple Executions
Normally, the setup
function executes only once, but it may re-execute during hot updates in development mode:
// Hot-reload example in development
let setupCount = 0
setup() {
setupCount++
console.log(`Setup executed ${setupCount} times`)
// The count will increase during hot updates
return {}
}
Integration with provide/inject
The setup
function is the best place to use provide
because its execution timing precedes the creation of descendant components:
// Ancestor component
setup() {
provide('theme', 'dark') // Available before descendant components are created
}
// Descendant component
setup() {
const theme = inject('theme') // Can be accessed immediately
}
Performance Optimization Considerations
Since the setup
function executes synchronously during component creation, heavy operations should be avoided:
// Not recommended
setup() {
// Synchronously executing heavy operations blocks component initialization
processLargeData()
// Recommended: place async operations in onMounted
onMounted(async () => {
await loadHeavyResources()
})
}
TypeScript Type Inference
The early execution of the setup
function also affects how the type system works:
interface Props {
id: number
}
setup(props: Props) {
// Prop types are determined when setup executes
const doubleId = computed(() => props.id * 2)
return { doubleId }
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:自定义指令的编译处理
下一篇:生命周期钩子的注册机制