Chapter 88: Vue ‘methods’ Option
The methods option
This is the original, classic way to define functions (methods) inside a Vue component — the way Vue worked from the very beginning (Vue 1 → Vue 2 → early Vue 3), and the way millions of legacy projects, tutorials, job interview questions, and old Stack Overflow answers still use it in 2026.
Even if you personally write only <script setup> + Composition API today (which is the modern recommendation), you must understand the methods option properly because:
- You will read/maintain old code written this way
- Many job interviews (especially in India) still ask about it
- Some advanced patterns (mixins, plugins, global components) are still written using Options API
- Vue Devtools still shows methods in this format
So let’s go through it step by step — like I’m pair-programming with you and explaining both the old world and why we mostly moved away from it.
1. What is the methods option? (Very simple mental model)
methods is a plain object where each key is the name of a function, and each value is the function itself.
Vue takes this object and attaches all those functions to the component instance, so you can call them from the template or from other methods using this.methodName().
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
methods: { increment() { this.count++ }, reset() { this.count = 0 }, async fetchUser() { this.isLoading = true try { const res = await fetch('/api/user') this.user = await res.json() } catch (err) { console.error(err) } finally { this.isLoading = false } } } |
After Vue processes this:
- this.increment() becomes available everywhere in the component
- You can write @click=”increment” in the template
- All this inside methods refers to the component instance (has access to this.data, this.computed, this.$refs, etc.)
2. Real, Complete Example – Todo List with Methods
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
<template> <div class="todo-app"> <h2>Options API – methods example</h2> <div class="input-row"> <input v-model.trim="newTask" placeholder="Add new task..." @keyup.enter="addTask" /> <button @click="addTask">Add</button> </div> <ul> <li v-for="todo in todos" :key="todo"> {{ todo }} <button @click="removeTodo(todo)">×</button> </li> </ul> <p>{{ remaining }} remaining</p> </div> </template> <script> export default { name: 'TodoApp', data() { return { newTask: '', todos: ['Learn Vue', 'Understand methods option'] } }, computed: { remaining() { return this.todos.length } }, // ── This is the methods option ─────────────────────────────── methods: { addTask() { if (!this.newTask.trim()) return // 'this' gives access to data, computed, other methods this.todos.push(this.newTask.trim()) this.newTask = '' }, removeTodo(todoText) { this.todos = this.todos.filter(t => t !== todoText) }, clearAll() { if (confirm('Clear all tasks?')) { this.todos = [] } }, // Example of method calling another method resetAndNotify() { this.clearAll() this.notify('All tasks cleared!') }, // Example of async method async notify(message) { alert(message) // In real app: could call toast library, send analytics, etc. } }, mounted() { console.log('Mounted – I can call methods here too') this.notify('Welcome to the todo app!') } } </script> <style scoped> .todo-app { padding: 2rem; max-width: 500px; margin: 2rem auto; background: white; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); } .input-row { display: flex; gap: 0.8rem; margin-bottom: 1.5rem; } input { flex: 1; padding: 0.9rem; border: 1px solid #d1d5db; border-radius: 6px; } button { padding: 0.9rem 1.6rem; background: #3b82f6; color: white; border: none; border-radius: 6px; cursor: pointer; } ul { list-style: none; padding: 0; } li { padding: 0.8rem; background: #f8fafc; margin: 0.5rem 0; border-radius: 6px; display: flex; justify-content: space-between; align-items: center; } </style> |
3. Important Rules & Gotchas (2026 Must-Know)
| Rule / Gotcha | Correct Behavior / Best Practice |
|---|---|
| methods must be an object | methods: { increment() { … } } — never an array or function |
| All methods get this bound automatically | this inside methods = component instance (access this.count, this.$refs, etc.) |
| Can call other methods | Yes — this.resetAndNotify() calls this.clearAll() and this.notify() |
| Can be async | Yes — async fetchUser() { await … } works perfectly |
| Can be called from template | Yes — @click=”increment”, @keyup.enter=”submit” |
| Arrow functions? | Avoid — increment: () => {} loses this binding → this becomes undefined |
| Can I define computed-like logic? | No — use computed for cached values; methods are for actions |
| Still used in 2026? | Yes — in legacy code, some plugins, interviews, but not in new <script setup> code |
4. Modern Vue 3 – Why We Almost Never Use methods Anymore
In <script setup> (the 2026 standard):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<script setup> import { ref } from 'vue' const count = ref(0) const newTask = ref('') const todos = ref(['Learn Vue', 'Master reactivity']) // Just normal functions — no `methods` object function increment() { count.value++ } function addTask() { if (!newTask.value.trim()) return todos.value.push(newTask.value.trim()) newTask.value = '' } </script> |
→ No methods object → No this → Functions are just normal JavaScript at the top level → Same power, much cleaner & type-safe with TypeScript
Quick Summary Table – methods in 2026
| Question | Options API (legacy) | Composition API (<script setup>) | What you should do in new code |
|---|---|---|---|
| How to define functions? | methods: { increment() { … } } | normal function increment() { … } | Composition API |
| Access in template | @click=”increment” | @click=”increment” | — |
| Access inside function | this.count | count.value | — |
| Still used in 2026? | Yes — in legacy code, some plugins, interviews | Almost never (except legacy migration) | Avoid unless maintaining old code |
| TypeScript friendly? | Poor | Excellent (normal functions + types) | Use Composition |
Final 2026 Advice from Real Projects
- In new projects → you should never write methods: { … } — just define functions at the top level in <script setup>
- When you see methods → it means Options API (legacy style)
- Learn to read Options API — many jobs, open-source projects, tutorials still use it
- Never teach beginners methods as primary — start with normal functions in <script setup>
- If migrating old code → gradually convert methods → normal functions, data() → ref / reactive, etc.
Your mini homework:
- Create the todo component above in Options API
- Click buttons → see methods work with this
- Console.log this inside a method → see the component instance
- Convert it to <script setup> → compare readability & TypeScript support
Any part confusing? Want to see:
- Full Options API vs Composition API side-by-side project?
- How methods looks in Vue Devtools?
- Common bugs when using arrow functions in methods?
- Real component written in both styles?
Just tell me — we’ll convert and compare together step by step 🚀
