LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 2315 min read

<script setup>

Understand exactly what <script setup> compiles to, and the special compiler macros it provides.

What <script setup> Compiles To

<script setup> is compile-time syntactic sugar. Vite's Vue compiler transforms it into an equivalent setup() function, automatically returning everything you declared at the top level — no manual return statement, no manual components registration.

<!-- What you write -->
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
// Roughly what it compiles to
export default {
setup() {
const count = ref(0);
return { count };
},
};

Compiler Macros

defineProps and defineEmits, which you've already used, are compiler macros — special functions that only work inside <script setup> and don't need to be imported, because the compiler recognizes and transforms them directly.

<script setup>
const props = defineProps({ title: String });
const emit = defineEmits(['submit']);
</script>

Top-Level Bindings Are Automatically Exposed

Every variable, function, and import declared at the top level of <script setup> is automatically available in the template — this is what removes the need for an explicit return statement compared to a plain setup() function.

<script setup>
import { ref } from 'vue';
import AppButton from './AppButton.vue'; // available in the template automatically
const message = ref('Hello');
function greet() {
console.log(message.value);
}
</script>
<template>
<AppButton @click="greet">{{ message }}</AppButton>
</template>

defineExpose

By default, a <script setup> component's internals are private to a parent holding a template ref to it. defineExpose explicitly opts specific properties or methods into being accessible that way.

<script setup>
import { ref } from 'vue';
const inputValue = ref('');
function focus() {
// ... focus logic
}
defineExpose({ focus }); // parent can call childRef.value.focus()
</script>

FAQs

Yes — a plain <script> block alongside <script setup> is useful for named exports (like a component's name) that <script setup> alone can't declare.

No — defineProps, defineEmits, and defineExpose are compiler-level macros, automatically available inside <script setup> with no import statement.

Summary

<script setup> is sugar over setup(), with compiler macros and automatic template exposure removing most of the boilerplate. Next, you'll learn the lifecycle hooks available in the Composition API.

Next Lesson →

Lifecycle Hooks