0Pricing
Frontend Academy · Lesson

The setup() Function and script setup

Write logic in the setup() function or use the sugar, expose values to the template, and understand lifecycle hooks in Composition API.

The setup() Function and script setup is a free Frontend Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Frontend Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

The setup() Function

In Vue 3's Composition API, setup() is a component option that replaces data, methods, computed, and watch. It receives props and the setup context as arguments and returns what the template needs.

export default {
  props: { userId: String },
  setup(props, { emit, attrs, slots }) {
    const user = ref(null);
    onMounted(async () => {
      user.value = await fetchUser(props.userId);
    });
    return { user }; // must return what template uses
  }
};

<script setup> — Syntax Sugar

<script setup> is compile-time syntax sugar for setup(). Everything declared at the top level is automatically available in the template. No return statement needed.

<script setup lang="ts">
import { ref, onMounted } from 'vue';

const count = ref(0);
// count is automatically available in template
</script>

Lifecycle Hooks in setup()

Vue 3 lifecycle hooks are imported functions: onMounted, onUpdated, onUnmounted, onBeforeMount, onBeforeUpdate, etc. They can be called multiple times to register multiple handlers.

<script setup>
import { onMounted, onUnmounted } from 'vue';

let timer: ReturnType<typeof setInterval>;

onMounted(() => {
  timer = setInterval(tick, 1000);
  console.log('Component mounted');
});

onUnmounted(() => {
  clearInterval(timer); // cleanup
});
</script>

setup() Props

In setup(), props are reactive. Don't destructure them directly — use toRefs(props) or access via props.x to maintain reactivity.

const props = defineProps<{ userId: string }>();

// Reactive access:
watch(() => props.userId, (id) => fetchUser(id));

// toRefs for destructuring:
const { userId } = toRefs(props);

defineExpose() — Exposing to Parent

By default,