Examples
Six worked Vue 3 examples: SFC, props/emits, computed, watch, composables, Pinia.
Vue — examples
EXAMPLE
<!-- ===== 1. SFC counter ===== -->
<script setup>
import { ref, computed } from 'vue';
const count = ref(0);
const doubled = computed(() => count.value * 2);
</script>
<template>
<button @click="count++">{{ count }} (x2 = {{ doubled }})</button>
</template>
<!-- ===== 2. Props + emits ===== -->
<!-- Child.vue -->
<script setup>
const props = defineProps({ user: { type: Object, required: true } });
const emit = defineEmits(['save']);
</script>
<template>
<div>
<h2>{{ user.name }}</h2>
<button @click="emit('save', user.id)">Save</button>
</div>
</template>
<!-- App.vue -->
<Child :user="{ id: 1, name: 'Alex' }" @save="(id) => console.log(id)" />
<!-- ===== 3. Watch ===== -->
<script setup>
import { ref, watch } from 'vue';
const search = ref('');
watch(search, async (q) => {
if (q.length < 2) return;
const r = await fetch('/api/search?q=' + q);
results.value = await r.json();
}, { debounce: 300 }); // requires @vueuse/core
</script>
<!-- ===== 4. Async data with Suspense ===== -->
<!-- AsyncList.vue -->
<script setup>
const r = await fetch('/api/users');
const users = await r.json();
</script>
<template>
<ul><li v-for="u in users" :key="u.id">{{ u.name }}</li></ul>
</template>
<!-- App.vue -->
<Suspense>
<template #default><AsyncList /></template>
<template #fallback><p>Loading...</p></template>
</Suspense>
<!-- ===== 5. Composable (useCounter) ===== -->
// useCounter.ts
import { ref } from 'vue';
export function useCounter(start = 0) {
const value = ref(start);
const inc = () => value.value++;
const dec = () => value.value--;
const reset = () => value.value = start;
return { value, inc, dec, reset };
}
// In a component:
<script setup>
import { useCounter } from './useCounter';
const { value, inc, reset } = useCounter(10);
</script>
<template><button @click="inc">{{ value }}</button></template>
<!-- ===== 6. Pinia store ===== -->
// stores/cart.ts
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
export const useCart = defineStore('cart', () => {
const items = ref([]);
const total = computed(() => items.value.reduce((s, i) => s + i.price * i.qty, 0));
function add(item) { items.value.push(item); }
function remove(id) { items.value = items.value.filter(i => i.id !== id); }
return { items, total, add, remove };
});
<!-- Component -->
<script setup>
import { useCart } from '@/stores/cart';
const cart = useCart();
</script>
<template>
<p>Items: {{ cart.items.length }}; total: {{ cart.total }}</p>
<button @click="cart.add({ id: 1, price: 100, qty: 1 })">Add</button>
</template>
<!-- ===== Patterns ===== -->
<!-- - <script setup> + composition API for new code -->
<!-- - Composables for reusable reactive logic -->
<!-- - Pinia stores for cross-tree state -->
<!-- - Suspense for async data; useFetch in Nuxt -->
<!-- - v-model:fieldName for compound two-way bindings -->
<!-- ===== Pitfalls ===== -->
<!-- - Mutating props directly -->
<!-- - Destructuring reactive() -> loses reactivity -->
<!-- - Watch on whole object without deep: true -->
<!-- - GlobalScope-style mutating refs across modules -->
Why it matters
Six worked Vue examples cover the daily reflexes: SFC, props + emits, watch, async + Suspense, composable, Pinia store. Pin them as the start of any new Vue project.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
<!-- Component samples in lesson body. --> <template><h1>Vue Examples</h1></template>Try it Yourself »
Discussion
Loading…