Skip to content

Composition API Basic Rules

10.1.1. Fundamental Principles

  • <script setup> is mandatory. Options API must not be used.
  • TypeScript is mandatory. The <script> tag in .vue files must always include lang="ts".
  • Block order within an SFC (Single File Component) must follow <script> then <template> then <style>.
vue
<script setup lang="ts">
import { ref, computed } from 'vue'

const count = ref(0)
const doubled = computed(() => count.value * 2)
</script>

<template>
  <div>
    <p>{{ doubled }}</p>
    <button @click="count++">Increment</button>
  </div>
</template>

<style scoped>
/* Styles */
</style>

10.1.2. Composable Authoring Rules

  • Composable function names must start with the use prefix.
  • Files must be placed in the src/composables/ directory.
  • Each file must define exactly one composable.
typescript
// src/composables/useUser.ts
import { ref } from 'vue'
import { fetchUser } from '@/api/user'
import type { User } from '@/types/user'

export function useUser(userId: string) {
  const user = ref<User | null>(null)
  const loading = ref(false)
  const error = ref<Error | null>(null)

  async function load() {
    loading.value = true
    try {
      user.value = await fetchUser(userId)
    } catch (e) {
      error.value = e as Error
    } finally {
      loading.value = false
    }
  }

  return { user, loading, error, load }
}

10.1.3. ref and reactive Usage Rules

  • Use ref for primitive types (string, number, boolean).
  • Use ref as the default for object/array types as well. reactive should be used only sparingly, limited to cases where reactivity tracking is needed for deeply nested objects.
  • Access ref values explicitly via .value. In templates, they are automatically unwrapped.
typescript
// Correct
const name = ref<string>('')
const items = ref<Item[]>([])
const form = ref<FormData>({ name: '', email: '' })

// Limited use — reactive
const state = reactive<FormState>({
  fields: { name: '', email: '' },
  errors: {},
  isSubmitting: false,
})

10.1.4. Lifecycle Hooks

  • Use Composition API lifecycle hooks. Options API lifecycle methods such as created and mounted must not be used.
  • Code executed directly within <script setup> corresponds to created/beforeCreate. No separate hook is needed.
Options APIComposition APIPurpose
mountedonMountedDOM access, external library initialization
unmountedonUnmountedEvent listener removal, timer cleanup
updatedonUpdatedPost-DOM-update processing (minimize use)
beforeUnmountonBeforeUnmountBegin cleanup operations
typescript
import { onMounted, onUnmounted } from 'vue'

onMounted(() => {
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
})

TIENIPIA QUALIFIED STANDARD