Chapter 110: Vue Exercises
Vue-exercises, and let’s do what real teachers should do after theory:
Hands-on exercises — the only way you actually learn Vue.
I’m not going to give you 50 tiny “print hello world” tasks. Instead, I’m giving you 10 carefully sequenced, realistic exercises that build on each other, cover 90% of what real Vue developers do every week, and prepare you for medium-to-large real projects.
Each exercise has:
- clear goal
- starter code (or empty file if you want full challenge)
- hints (but try without them first)
- expected outcome / acceptance criteria
- bonus / stretch goals (for when you finish early)
You should do them in order — they gradually increase difficulty and combine concepts.
Let’s start.
Exercise 1 – Basic Counter with Composition API + reactivity fundamentals
Goal: Build a simple counter that shows all basic reactivity patterns.
File: Counter.vue
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<script setup> import { ref, computed } from 'vue' // Your code here </script> <template> <div class="counter"> <h2>Counter Exercise</h2> <!-- your UI here --> </div> </template> |
Requirements:
- Two buttons: +1 and Reset
- Show current count
- Show “Even” / “Odd” label that updates instantly
- Show “High score” that remembers the maximum value ever reached
- Disable +1 button when count ≥ 20 (show message “Limit reached”)
- Add a text input → show live “Double count would be: XX” below it (use .number modifier)
Acceptance criteria:
- Count increases/decreases correctly
- Even/Odd updates immediately
- High score persists even after reset
- Button disables at 20
- Double preview works with number input
Hints (only look after 15 min struggle):
- Use ref for count, highScore, inputValue
- Use computed for isEven, doublePreview, isMaxReached
- Use ternary in template for disable + message
Bonus:
- Add –1 button (but never go below 0)
- Add keyboard shortcut: press ArrowUp → +1, ArrowDown → –1
Exercise 2 – Todo List with TransitionGroup + emits + v-for + key
Goal: Build classic todo list — but with animations and clean separation (child emits, parent manages state)
Files:
- TodoApp.vue (parent)
- TodoItem.vue (child)
Requirements:
- Input + Add button (or Enter)
- List with checkbox + text + delete button
- Checkbox toggles done state → strikethrough + fade animation
- Delete item → leave animation (slide out)
- Show “X items left” counter
- Filter: All / Active / Completed buttons
- Clear Completed button
Acceptance criteria:
- Add / toggle / delete works
- Animations are smooth (use <TransitionGroup name=”list”>)
- Filter updates instantly
- Correct items-left count
- :key is used correctly (use id, not index)
Bonus:
- Add edit on double-click (input appears, save on Enter/Blur)
- Persist todos in localStorage (use watch + onMounted)
Exercise 3 – Tabs with <KeepAlive> + onActivated / onDeactivated
Goal: Build tabbed interface where each tab preserves state (input value, scroll position)
Requirements:
- Three tabs: Overview, Notes, Settings
- Use <KeepAlive>
- Each tab has:
- textarea (Notes tab)
- long scrollable dummy content (Overview tab)
- checkbox + number input (Settings tab)
- Switch tabs 10 times → verify:
- textarea content preserved
- scroll position preserved in Overview
- checkbox & number value preserved in Settings
Acceptance criteria:
- State survives tab switches
- onActivated restores scroll
- onDeactivated saves scroll
- No re-mount flicker (use Devtools to confirm)
Bonus:
- Add fade transition between tabs
- Add “last visited” timestamp per tab (shown in header)
Exercise 4 – Form with multiple v-model + validation + error handling
Goal: Build signup form with real validation logic
Requirements:
- Fields: name, email, password, confirm password, age (number), country (select), interests (checkbox group)
- Live validation messages (red text below fields)
- Submit button disabled until form valid
- Show success message on submit (fake delay 1.5s)
- Use .trim, .number, .lazy where appropriate
Acceptance criteria:
- Name ≥ 3 chars
- Email has @
- Password ≥ 8 chars, match confirm
- Age ≥ 18
- Country selected
- At least 1 interest checked
- Button disables correctly
- Success message appears after submit
Bonus:
- Add password strength indicator (weak/medium/strong)
- Show/hide password toggle button
Exercise 5 – Modal system with Teleport + Transition + expose + slots
Goal: Build reusable modal with programmatic control
Requirements:
- <Modal> component with v-model support
- Expose open(), close() methods via defineExpose
- Named slots: header, default (body), footer
- Close on overlay click + Esc key
- Prevent background scroll when open
- Animation (fade + scale)
Acceptance criteria:
- Open/close from parent via ref or v-model
- Slots work (custom header/footer)
- Esc closes modal
- Body scroll disabled when open (use class on <body>)
Bonus:
- Add confirm event
- Add loading state (spinner in footer)
Exercise 6 – Error Boundary + Suspense + async component
Goal: Build crash-proof section with loading & error handling
Requirements:
- <ErrorBoundary> component using onErrorCaptured
- Wrap <Suspense> around lazy-loaded component
- Create dummy async component that sometimes throws error
- Show fallback UI on error + retry button
Acceptance criteria:
- Error in child → fallback shown, app doesn’t crash
- Slow-loading child → Suspense fallback shown
- Retry button resets error state
Bonus:
- Send error to console/Sentry-like service
- Add loading spinner inside Suspense
Exercise 7 – Dashboard with KeepAlive + Transition + v-memo + performance
Goal: Build mini dashboard that shows performance patterns
Requirements:
- Tabs: Overview, Analytics, Settings
- Use <KeepAlive>
- Analytics tab has fake heavy chart (use v-memo to prevent re-render on tab switch)
- Add live clock (setInterval) → pause in onDeactivated
- Add scrollable news feed → restore scroll in onActivated
Acceptance criteria:
- Tab switch is instant (KeepAlive)
- Chart doesn’t re-render unnecessarily (v-memo)
- Clock pauses when tab hidden
- Scroll position restored when returning
Bonus:
- Add onRenderTriggered temporarily → prove chart is not re-rendered on tab switch
Final Words – How to Approach These Exercises
- Create one new Vue project (Vite + Vue 3 + TypeScript)
- Make one component per exercise
- Commit after each one (git commit -m “Exercise 3: Tabs with KeepAlive”)
- Use Vue Devtools constantly — watch reactivity graph, timeline, component tree
- After finishing all 7 → try combining 3–4 of them into one mini-app (dashboard + modal + tabs + error boundary)
Any exercise confusing? Want starter code / solution hints / full repo link for any of them?
Just tell me which one — we’ll build it together live, line by line 🚀
