阿里云主机折上折
  • 微信号
Current Site:Index > The execution timing of the setup function

The execution timing of the setup function

Author:Chuan Chen 阅读数:40101人阅读 分类: Vue.js

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:

  1. Initialize props and slots
  2. Execute the setup function
  3. 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

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.