A compact Vue 3 crash course cheatsheet with examples from Lection 1–10.
Perfect for quick refreshers, workshops, and reference.
- Quick Start (CDN)
- Forms & v-model
- Core Directives
- Computed vs Methods vs Watchers
- Components, Props & Events
- Dynamic Components & Keep-Alive
- Lifecycle Hooks
- Composition API
- Full Code Examples (Lection 1–10)
Quick start, directives, forms, computed vs methods vs watchers, components, dynamic components, lifecycle, Composition API.
Drop this into an index.html and you’re ready:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Vue Quick Start</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script>
const { createApp } = Vue;
const app = createApp({
data() { return { message: "Hello Vue!" } }
}).mount("#app");
</script>
</body>
</html>Two‑way binding:
<input v-model="name" placeholder="Your name">
<p>Hello, {{ name }}!</p>Checkbox / Radio / Select:
<input type="checkbox" v-model="accepted"> Terms
<input type="radio" value="a" v-model="choice"> A
<input type="radio" value="b" v-model="choice"> B
<select v-model="country">
<option disabled value="">Pick one</option>
<option>Germany</option>
<option>UK</option>
</select>💡 v-model ≈ :value + @input
Bind attributes:
<img :src="avatarUrl" :alt="username">
<a :href="profileLink">{{ username }}</a>Events, conditionals:
<button @click="count++">Clicked {{ count }}</button>
<p v-if="loggedIn">Welcome</p>
<p v-else>Please log in</p>
<p v-show="debug">Debug panel</p>Lists + class/style:
<li v-for="user in users" :key="user.id">{{ user.name }}</li>
<p :class="{ active: isActive, danger: hasError }">Status</p>
<p :style="{ fontSize: size + 'px' }">Big text</p>Methods – run every render
methods: {
randomNumber() { return Math.random() }
}Computed – cached until deps change
computed: {
fullName() { return this.firstName + " " + this.lastName }
}Watchers – side effects
watch: {
email(newVal) { this.valid = newVal.includes("@") }
}💡 Rule of thumb: Computed for derived values, Methods for actions, Watchers for effects
Register + use:
app.component("user-card", {
props: ["username", "role"],
template: `<div><strong>{{ username }}</strong> ({{ role }})</div>`
})<user-card :username="u.name" :role="u.role"></user-card>Events up:
<!-- Child -->
<button @click="$emit('remove', id)">Remove</button>
<!-- Parent -->
<user-card @remove="removeUser"></user-card>methods: { removeUser(id){ /* ... */ } }List of components:
<user-card v-for="u in users"
:key="u.id" :username="u.name" :role="u.role">
</user-card><button @click="current='home-view'">Home</button>
<button @click="current='profile-view'">Profile</button>
<keep-alive>
<component :is="current"></component>
</keep-alive>💡 Switch with <component :is>. Use <keep-alive> to preserve state.
created(){ /* data ready */ }
mounted(){ /* in DOM */ }
updated(){ /* after reactive changes */ }
unmounted(){ /* cleanup */ }const { ref, computed, watch } = Vue
createApp({
setup() {
const count = ref(0)
const double = computed(() => count.value * 2)
function inc(){ count.value++ }
watch(count, (n,o) => console.log(o, "→", n))
return { count, double, inc }
}
}).mount("#app")<div id="app">
<p>Count: {{ count }}</p>
<p>Double: {{ double }}</p>
<button @click="inc">+1</button>
</div>Jump to:
- Lection 1 – Introduction & Basics
- Lection 2 – v-model Forms
- Lection 3 – Core Directives
- Lection 4 – Computed & Watchers
- Lection 5 – Methods vs Computed vs Watchers
- Lection 6 – Components & Lists
- Lection 7 – Props & Events
- Lection 8 – Dynamic Components & Keep-Alive
- Lection 9 – Lifecycle Hooks
- Lection 10 – Composition API
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Vue Intro</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<h1>{{ message }}</h1>
</div>
<script>
const { createApp } = Vue;
const app = createApp({
data() {
return { message: "Hello Vue!" };
}
}).mount("#app");
</script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue v-model Example</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<h2>Text Input</h2>
<input v-model="name" placeholder="Enter your name">
<p>Hello, {{ name }}!</p>
<h2>Textarea</h2>
<textarea v-model="message" placeholder="Write something..."></textarea>
<p>You wrote: {{ message }}</p>
<h2>Checkbox</h2>
<input type="checkbox" v-model="accepted"> Accept terms?
<p>Accepted: {{ accepted }}</p>
<h2>Radio Buttons</h2>
<input type="radio" value="male" v-model="gender"> Male
<input type="radio" value="female" v-model="gender"> Female
<p>Gender: {{ gender }}</p>
<h2>Select Dropdown</h2>
<select v-model="country">
<option disabled value="">Please select</option>
<option>USA</option>
<option>UK</option>
<option>Germany</option>
</select>
<p>Selected country: {{ country }}</p>
</div>
<script>
const { createApp } = Vue;
const app = createApp({
data() {
return {
name: "",
message: "",
accepted: false,
gender: "",
country: ""
};
}
}).mount("#app");
</script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Vue Directives Playground</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
.active { color: green; font-weight: bold; }
.danger { color: crimson; }
.badge { padding: 2px 6px; border: 1px solid #ccc; border-radius: 4px; }
.info { background: #eef; }
.warn { background: #ffe; }
</style>
</head>
<body>
<div id="app">
<h1>Vue Directives</h1>
<!-- v-bind (:) -->
<h2>v-bind</h2>
<img :src="avatarUrl" :alt="username + ' avatar'" width="60">
<p>User: <a :href="profileLink" target="_blank">{{ username }}</a></p>
<!-- v-on (@) -->
<h2>v-on</h2>
<button @click="count++">Clicked {{ count }} times</button>
<div>
<input v-model="live" placeholder="Type here">
<p>Live: {{ live }}</p>
</div>
<!-- v-if / v-else -->
<h2>v-if / v-else</h2>
<button @click="loggedIn = !loggedIn">Toggle Login</button>
<p v-if="loggedIn">Welcome back, {{ username }}!</p>
<p v-else>Please log in to continue.</p>
<!-- v-show -->
<h2>v-show</h2>
<label><input type="checkbox" v-model="debug"> Show debug</label>
<pre v-show="debug">State: {{ $data }}</pre>
<!-- v-for -->
<h2>v-for</h2>
<ul>
<li v-for="user in users" :key="user.id">
{{ user.name }} — <em>{{ user.role }}</em>
</li>
</ul>
<!-- :class and :style -->
<h2>:class / :style</h2>
<label><input type="checkbox" v-model="isActive"> Active</label>
<label><input type="checkbox" v-model="hasError"> Error</label>
<label><input type="checkbox" v-model="faded"> Faded</label>
<div :class="{ active: isActive, danger: hasError }"
:style="{ fontSize: size + 'px', opacity: faded ? 0.5 : 1 }">
Dynamic style / class text
</div>
<label>Size: <input type="range" min="12" max="48" v-model.number="size"></label>
<p :class="['badge', badgeType]">Badge with array class</p>
<select v-model="badgeType">
<option value="info">info</option>
<option value="warn">warn</option>
</select>
</div>
<script>
const { createApp } = Vue;
const app = createApp({
data() {
return {
username: "amy",
profileLink: "https://example.com/u/amy",
avatarUrl: "https://avatars.githubusercontent.com/u/9919?s=60&v=4",
count: 0,
live: "",
loggedIn: false,
debug: false,
users: [
{ id: 1, name: "Amy", role: "Admin" },
{ id: 2, name: "Milan", role: "Editor" },
{ id: 3, name: "Sophy", role: "Viewer" }
],
isActive: true,
hasError: false,
faded: false,
size: 18,
badgeType: "info"
};
}
}).mount("#app");
</script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Vue – Computed & Watcher</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<h1>Computed & Watcher</h1>
<h2>Computed full name</h2>
<input v-model="firstName" placeholder="First name">
<input v-model="lastName" placeholder="Last name">
<p>Full name: {{ fullName }}</p>
<h2>Watcher email validation</h2>
<input v-model="email" placeholder="Enter email">
<p>Status: {{ status }}</p>
</div>
<script>
const { createApp } = Vue;
const app = createApp({
data() {
return {
firstName: "",
lastName: "",
email: "",
status: "Waiting..."
};
},
computed: {
fullName() { return this.firstName + " " + this.lastName; }
},
watch: {
email(newVal) {
this.status = newVal.includes("@") ? "Looks good ✅" : "Invalid email ❌";
}
}
}).mount("#app");
</script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Vue – Methods vs Computed vs Watchers (Clarified)</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
body { font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; line-height: 1.4; padding: 20px; }
.box { border: 1px solid #ddd; padding: 12px; border-radius: 8px; margin: 12px 0; }
</style>
</head>
<body>
<div id="app">
<h1>Methods vs Computed vs Watchers – Re-render Demo</h1>
<div class="box">
<h2>Re-render triggers</h2>
<button @click="forceRender++">Force re-render</button>
<button @click="count++">Increase count</button>
<p><strong>forceRender:</strong> {{ forceRender }}</p>
<p><strong>count:</strong> {{ count }}</p>
</div>
<div class="box">
<h2>Method (no caching)</h2>
<p>Method value: <strong>{{ randomNumber() }}</strong></p>
</div>
<div class="box">
<h2>Computed (cached until dependency changes)</h2>
<p>Computed value: <strong>{{ randomNumberCached }}</strong></p>
<button @click="seed++">Change seed (refresh computed)</button>
<p><strong>seed:</strong> {{ seed }}</p>
</div>
<div class="box">
<h2>Watcher (side effects)</h2>
<p>Status: {{ status }}</p>
</div>
</div>
<script>
const { createApp } = Vue;
const app = createApp({
data() {
return {
forceRender: 0,
count: 0,
status: "Not yet 5",
seed: 1
};
},
methods: {
randomNumber() { return Math.random(); }
},
computed: {
randomNumberCached() {
// Depends on seed -> only changes when seed changes
return Math.random() * this.seed;
}
},
watch: {
count(newVal) {
this.status = newVal >= 5 ? "Reached 5 or more!" : "Not yet 5";
}
}
}).mount("#app");
</script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Vue Components & Lists</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
.card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 12px;
margin: 8px 0;
background: #f9f9f9;
}
.role { font-size: 0.9em; color: #666; }
</style>
</head>
<body>
<div id="app">
<h1>User List</h1>
<user-card
v-for="user in users"
:key="user.id"
:username="user.name"
:role="user.role">
</user-card>
<button @click="addUser">Add random user</button>
</div>
<script>
const { createApp } = Vue;
const app = createApp({
data() {
return {
users: [
{ id: 1, name: "Amy", role: "Admin" },
{ id: 2, name: "Milan", role: "Editor" },
{ id: 3, name: "Sophy", role: "Viewer" }
]
};
},
methods: {
addUser() {
const id = this.users.length + 1;
const names = ["Tom", "Maggy", "Zahira", "Ed"];
const roles = ["Guest", "Member", "Owner"];
const name = names[Math.floor(Math.random() * names.length)];
const role = roles[Math.floor(Math.random() * roles.length)];
this.users.push({ id, name, role });
}
}
});
app.component("user-card", {
props: ["username", "role"],
template: `
<div class="card">
<strong>{{ username }}</strong>
<div class="role">{{ role }}</div>
</div>
`
});
app.mount("#app");
</script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Vue – Props & Events</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
.card { border: 1px solid #ddd; border-radius: 6px; padding: 10px; margin: 6px 0; }
.role { font-size: 0.9em; color: #555; }
button { margin-left: 10px; }
</style>
</head>
<body>
<div id="app">
<h1>User List</h1>
<user-card
v-for="user in users"
:key="user.id"
:username="user.name"
:role="user.role"
@remove="removeUser(user.id)">
</user-card>
<button @click="addUser">Add random user</button>
</div>
<script>
const { createApp } = Vue;
const app = createApp({
data() {
return {
users: [
{ id: 1, name: "Amy", role: "Admin" },
{ id: 2, name: "Milan", role: "Editor" },
{ id: 3, name: "Sophy", role: "Viewer" }
]
};
},
methods: {
addUser() {
const id = this.users.length + 1;
const names = ["Tom", "Maggy", "Zahira", "Ed"];
const roles = ["Guest", "Member", "Owner"];
const name = names[Math.floor(Math.random() * names.length)];
const role = roles[Math.floor(Math.random() * roles.length)];
this.users.push({ id, name, role });
},
removeUser(id) {
this.users = this.users.filter(u => u.id !== id);
}
}
});
app.component("user-card", {
props: ["username", "role"],
template: `
<div class="card">
<strong>{{ username }}</strong>
<span class="role">({{ role }})</span>
<button @click="$emit('remove')">Remove</button>
</div>
`
});
app.mount("#app");
</script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Vue – Dynamic Components</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
.tabs button { margin: 5px; padding: 5px 10px; }
.active { font-weight: bold; }
.view { border: 1px solid #ccc; padding: 10px; margin-top: 10px; }
</style>
</head>
<body>
<div id="app">
<h1>Dynamic Components (Tabs)</h1>
<div class="tabs">
<button
v-for="tab in tabs"
:key="tab"
@click="currentView = tab"
:class="{ active: currentView === tab }">
{{ tab }}
</button>
</div>
<keep-alive>
<component :is="currentView" class="view"></component>
</keep-alive>
</div>
<script>
const { createApp } = Vue;
const app = createApp({
data() {
return {
tabs: ["home-view", "about-view", "profile-view"],
currentView: "home-view"
};
}
});
app.component("home-view", {
template: `<div><h2>Home</h2><p>Welcome to the homepage!</p></div>`
});
app.component("about-view", {
template: `<div><h2>About</h2><p>This is an app built with Vue.</p></div>`
});
app.component("profile-view", {
data() {
return { name: "Amy" };
},
template: `
<div>
<h2>Profile</h2>
<p>Edit your name:</p>
<input v-model="name">
<p>Hi, {{ name }}!</p>
</div>`
});
app.mount("#app");
</script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Vue – Lifecycle Hooks</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<style>
.tabs button { margin: 5px; padding: 5px 10px; }
.active { font-weight: bold; }
.view { border: 1px solid #ccc; padding: 10px; margin-top: 10px; }
</style>
</head>
<body>
<div id="app">
<h1>Lifecycle Demo (Check Console)</h1>
<div class="tabs">
<button
v-for="tab in tabs"
:key="tab"
@click="currentView = tab"
:class="{ active: currentView === tab }">
{{ tab }}
</button>
</div>
<component :is="currentView" class="view"></component>
</div>
<script>
const { createApp } = Vue;
const app = createApp({
data() {
return {
tabs: ["home-view", "about-view"],
currentView: "home-view"
};
}
});
app.component("home-view", {
template: `<div><h2>Home</h2><p>Welcome to the homepage!</p></div>`,
created() { console.log("Home created"); },
mounted() { console.log("Home mounted"); },
updated() { console.log("Home updated"); },
unmounted() { console.log("Home unmounted"); }
});
app.component("about-view", {
data() { return { counter: 0 }; },
template: `
<div>
<h2>About</h2>
<p>This is an app built with Vue.</p>
<button @click="counter++">Counter: {{ counter }}</button>
</div>`,
created() { console.log("About created"); },
mounted() { console.log("About mounted"); },
updated() { console.log("About updated"); },
unmounted() { console.log("About unmounted"); }
});
app.mount("#app");
</script>
</body>
</html><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Vue – Composition API</title>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<h1>Options API</h1>
<p>Count: {{ count }}</p>
<p>Double: {{ double }}</p>
<button @click="increment">+1</button>
</div>
<div id="app2">
<h1>Composition API</h1>
<p>Count: {{ count }}</p>
<p>Double: {{ double }}</p>
<button @click="increment">+1</button>
</div>
<script>
const { createApp, ref, computed, watch } = Vue
// Options API
createApp({
data() {
return { count: 0 }
},
computed: {
double() { return this.count * 2 }
},
methods: {
increment() { this.count++ }
}
}).mount("#app")
// Composition API
createApp({
setup() {
const count = ref(0)
const double = computed(() => count.value * 2)
function increment() { count.value++ }
watch(count, (newVal, oldVal) => {
console.log("Count changed:", oldVal, "→", newVal)
})
return { count, double, increment }
}
}).mount("#app2")
</script>
</body>
</html>