Bird
Raised Fist0
Vueframework~10 mins

Script setup syntax in Vue - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Script setup syntax
Start: <script setup> block
↓
Declare reactive refs and variables
↓
Define functions and imports
↓
Template uses declared refs and functions
↓
Vue compiles and binds reactive data
↓
Component renders with reactive updates
The <script setup> block declares reactive variables and functions directly, which Vue compiles and binds to the template for reactive rendering.
Execution Sample
Vue
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
  count.value++
}
</script>
<template>
  <button @click="increment">Count: {{ count }}</button>
</template>
This Vue component uses <script setup> to declare a reactive count and an increment function, updating the button label on click.
Execution Table
StepActionVariable StateTemplate BindingRendered Output
1Import ref from VueNo variables yetNo bindingN/A
2Declare count = ref(0)count = 0 (reactive)count bound to templateButton shows 'Count: 0'
3Define increment functioncount unchangedincrement bound to click eventButton shows 'Count: 0'
4User clicks buttonincrement() called, count.value++count updates to 1Button updates to 'Count: 1'
5User clicks button againcount.value increments to 2count updates to 2Button updates to 'Count: 2'
6No more clickscount stable at 2No changeButton shows 'Count: 2'
ExitComponent remains reactivecount reactive and updatedTemplate reflects countRendered output matches count value
💡 User stops clicking; reactive count stabilizes and template shows latest value.
Variable Tracker
VariableStartAfter 1 ClickAfter 2 ClicksFinal
count.value0122
Key Moments - 3 Insights
Why do we use count.value instead of just count?
Because count is a reactive ref object, the actual number is inside count.value. The execution_table rows 4 and 5 show count.value being incremented.
How does the template know to update when count changes?
Vue automatically tracks reactive refs declared in <script setup> and updates the template when their values change, as seen in the rendered output changes in execution_table rows 4 and 5.
Can we define functions directly inside <script setup>?
Yes, functions like increment are defined directly and bound to the template events, shown in execution_table step 3 and 4.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 2, what is the value of count?
A0
Bundefined
Cref object
Dnull
💡 Hint
Check the 'Variable State' column at step 2 in execution_table.
At which step does the button label update to 'Count: 1'?
AStep 3
BStep 5
CStep 4
DStep 6
💡 Hint
Look at the 'Rendered Output' column in execution_table for when count changes to 1.
If we forgot to use count.value++ inside increment, what would happen?
AVue would throw an error
Bcount would not change and button label stays the same
Ccount would increment anyway
DButton label would show 'undefined'
💡 Hint
Refer to how count.value is updated in execution_table steps 4 and 5.
Concept Snapshot
Vue <script setup> syntax:
- Use <script setup> block for concise component logic
- Declare reactive refs with ref() and access via .value
- Define functions directly for template events
- Variables and functions auto-expose to template
- Vue tracks reactivity and updates DOM automatically
Full Transcript
This visual execution trace shows how Vue's <script setup> syntax works. We start by importing ref and declaring a reactive variable count with initial value 0. Then we define an increment function that increases count.value. The template binds count and the increment function to a button. When the button is clicked, increment runs, count.value increases, and Vue updates the button label reactively. The variable tracker shows count.value changing from 0 to 2 after two clicks. Key moments clarify why .value is needed and how template updates happen automatically. The quiz tests understanding of reactive state and template binding in <script setup>.

Practice

(1/5)
1. What is the main advantage of using <script setup> in a Vue component?
easy
A. It requires class-based components instead of functions.
B. It automatically adds CSS styles to the component.
C. It disables the use of reactive variables.
D. It removes the need for export default and simplifies code.

Solution

  1. Step 1: Understand the purpose of <script setup>

    This syntax is designed to simplify Vue components by removing boilerplate code like export default.
  2. Step 2: Compare options with this purpose

    Only It removes the need for export default and simplifies code. correctly states that it removes the need for export default and simplifies code.
  3. Final Answer:

    It removes the need for export default and simplifies code. -> Option D
  4. Quick Check:

    Script setup simplifies code = A [OK]
Hint: Remember script setup removes export default for simpler code [OK]
Common Mistakes:
  • Thinking script setup adds styles automatically
  • Believing reactive variables are disabled
  • Confusing script setup with class-based components
2. Which of the following is the correct way to declare a reactive variable inside <script setup>?
easy
A. let count = reactive(0);
B. const count = ref(0);
C. var count = reactiveRef(0);
D. const count = reactiveVar(0);

Solution

  1. Step 1: Recall Vue 3 Composition API reactive variable syntax

    Reactive variables use ref() to wrap primitive values like numbers.
  2. Step 2: Check each option

    const count = ref(0); uses ref(0), which is correct. Options A, C, and D use incorrect or non-existent functions.
  3. Final Answer:

    const count = ref(0); -> Option B
  4. Quick Check:

    Use ref() for reactive primitives = B [OK]
Hint: Use ref() for reactive primitives inside script setup [OK]
Common Mistakes:
  • Using reactive() for primitive values
  • Using undefined functions like reactiveRef or reactiveVar
  • Using var instead of const or let
3. Given the following <script setup> code, what will be rendered inside the template?
<script setup>
import { ref } from 'vue'
const message = ref('Hello')
message.value = 'Hi'
</script>

<template>
  <p>{{ message }}</p>
</template>
medium
A. <p>Hello</p>
B. Error: message is not defined
C. <p>Hi</p>
D. <p>[object Object]</p>

Solution

  1. Step 1: Understand how ref works in template interpolation

    In Vue, a ref is an object with a value property. To display the inner value, you must use message.value in script or just message in template because Vue unwraps refs in templates.
  2. Step 2: Check the template interpolation

    The template uses {{ message }}. Vue unwraps refs here, so it should display the string inside message.value, which is 'Hi'.
  3. Step 3: Identify the actual behavior

    In Vue 3 with <script setup>, refs are unwrapped automatically in templates, so it should display 'Hi'. The code sets message.value = 'Hi' correctly, so the output is 'Hi'.
  4. Final Answer:

    <p>Hi</p> -> Option C
  5. Quick Check:

    Template unwraps ref = Hi [OK]
Hint: Remember Vue unwraps refs automatically in templates [OK]
Common Mistakes:
  • Thinking you must write message.value in template
  • Confusing ref object with its value
  • Assuming message is undefined
4. Identify the error in the following <script setup> code snippet:
<script setup>
import { reactive } from 'vue'
const state = reactive({ count: 0 })
function increment() {
  state.count++
}
</script>

<template>
  <button @click="increment()">Increment</button>
  <p>Count: {{ state.count }}</p>
</template>
medium
A. There is no error; the code works correctly.
B. The increment function is not exposed to the template and cannot be called.
C. The reactive object should be declared with ref() instead of reactive().
D. The @click event syntax is incorrect; it should be v-on:click.

Solution

  1. Step 1: Analyze the reactive state and function

    The code uses reactive to create a reactive object state with a count property. The increment function modifies state.count.
  2. Step 2: Check template usage and event binding

    The template uses @click="increment()" which is valid shorthand for v-on:click. The function increment is defined in <script setup> and is automatically exposed to the template.
  3. Final Answer:

    There is no error; the code works correctly. -> Option A
  4. Quick Check:

    Script setup exposes functions automatically = C [OK]
Hint: Functions in script setup are auto-exposed to template [OK]
Common Mistakes:
  • Thinking reactive must be replaced by ref for objects
  • Believing functions need explicit export
  • Confusing @click with invalid syntax
5. You want to create a Vue component using <script setup> that fetches data asynchronously when the component mounts and stores it in a reactive variable. Which is the correct way to do this?
hard
A.
<script setup>
import { ref, onMounted } from 'vue'
const data = ref(null)
onMounted(async () => {
  const res = await fetch('https://api.example.com/data')
  data.value = await res.json()
})
</script>
B.
<script setup>
import { reactive } from 'vue'
const data = reactive(null)
async function fetchData() {
  const res = await fetch('https://api.example.com/data')
  data = await res.json()
}
fetchData()
</script>
C.
<script setup>
import { ref } from 'vue'
const data = ref(null)
fetch('https://api.example.com/data').then(res => {
  data = res.json()
})
</script>
D.
<script setup>
import { ref, onMounted } from 'vue'
const data = ref(null)
onMounted(() => {
  fetch('https://api.example.com/data').then(res => res.json()).then(json => {
    data.value = json
  })
})
</script>

Solution

  1. Step 1: Understand how to fetch data on component mount

    Use the onMounted lifecycle hook to run code after the component is ready.
  2. Step 2: Check reactive variable usage and async fetch

    Use ref(null) for reactive data. Inside onMounted, use async/await to fetch and assign data to data.value.
  3. Step 3: Evaluate each option

    <script setup>
    import { ref, onMounted } from 'vue'
    const data = ref(null)
    onMounted(async () => {
      const res = await fetch('https://api.example.com/data')
      data.value = await res.json()
    })
    </script>
    correctly uses ref, onMounted, and async/await with proper assignment to data.value.
    <script setup>
    import { reactive } from 'vue'
    const data = reactive(null)
    async function fetchData() {
      const res = await fetch('https://api.example.com/data')
      data = await res.json()
    }
    fetchData()
    </script>
    incorrectly tries to assign to a reactive object directly and calls fetchData immediately without lifecycle hook.
    <script setup>
    import { ref } from 'vue'
    const data = ref(null)
    fetch('https://api.example.com/data').then(res => {
      data = res.json()
    })
    </script>
    assigns data instead of data.value and lacks lifecycle hook.
    <script setup>
    import { ref, onMounted } from 'vue'
    const data = ref(null)
    onMounted(() => {
      fetch('https://api.example.com/data').then(res => res.json()).then(json => {
        data.value = json
      })
    })
    </script>
    uses promises correctly but
    <script setup>
    import { ref, onMounted } from 'vue'
    const data = ref(null)
    onMounted(async () => {
      const res = await fetch('https://api.example.com/data')
      data.value = await res.json()
    })
    </script>
    is cleaner and preferred with async/await.
  4. Final Answer:

    Option A code snippet -> Option A
  5. Quick Check:

    Use onMounted + ref + async/await = A [OK]
Hint: Use onMounted with async/await and ref for fetching data [OK]
Common Mistakes:
  • Assigning directly to reactive instead of .value
  • Not using lifecycle hooks for async fetch
  • Mixing reactive and ref incorrectly
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard