Modern JavaScript for Vue
Modules, arrow functions, destructuring, spread, promises and async/await.
Vue is "just JavaScript", and most Vue code you read relies on a dozen modern JavaScript features. If const { data } = await res.json() or [...items, newItem] looks odd to you, this lesson comes first.
Every section below has a Try it yourself editor. Change the code, press Run, and the result appears underneath. The editors run real Vue 3 in your browser, so you can practise the JavaScript and the Vue syntax together.
setup() function: Vue's ref, computed, watch and friends are already in scope, and whatever you return is available to the template.
const, let and template literals
Use const by default and let only when you reassign. Never use var. Template literals (backticks) interpolate with ${} and can span lines.
A const that holds a ref is fine: the variable never changes, the ref's .value does.
Arrow functions
Arrow functions are shorter and don't create their own this. That's why the Composition API (which never uses this) is full of them. A single expression after => is returned automatically; wrap an object literal in parentheses to return it.
Destructuring
Destructuring pulls values out of objects and arrays into variables. You'll see it on almost every line of Vue code: const { data } = await res.json(), const { id } = route.params, const [first, ...rest] = items.
const { count } = reactive({ count: 0 }) copies the number out once. Use toRefs() or keep using state.count. The How Vue Works lesson has a live demo of this.
Spread and immutable updates
The spread operator ... copies arrays and objects. It's the standard way to add, update or remove items without mutating the original, which matters for Pinia history, props you mustn't change and watch comparisons.
Array methods: map, filter, find, reduce
These four methods cover nearly every list operation in a Vue app, and they're what you put inside computed(). They return new values instead of changing the array.
| Method | Returns | Typical Vue use |
|---|---|---|
map |
new array, same length | turning API rows into view models |
filter |
new array, fewer items | search boxes, "show completed" toggles |
find |
first match or undefined |
selecting an item by id |
some / every |
boolean | "any errors?", "all done?" |
reduce |
any single value | totals, grouping into an object |
Optional chaining and nullish coalescing
Data from an API is often missing a field, for example a task without an assignee. ?. stops at null/undefined instead of throwing, and ?? supplies a default only for null/undefined (unlike ||, which also replaces 0 and '').
Modules: import and export
In a real project every .vue and .js file is an ES module. You export what other files may use and import it where needed. Vite resolves the imports and bundles them.
// src/composables/useTasks.js
export function useTasks() { /* ... */ } // named export
export default { perPage: 10 } // default export
// src/components/TaskBoard.vue
import { ref, computed } from 'vue' // named imports from a package
import { useTasks } from '@/composables/useTasks'
import settings from '@/composables/useTasks' // default import, any name
import because Vue is loaded from a CDN and its functions are already in scope. In an SFC you'd write import { ref } from 'vue' at the top of <script setup>.
Promises and async / await
Anything that takes time, like an HTTP request, returns a Promise. await pauses the async function until the promise settles, and try / catch / finally handles failures. This editor calls this site's real Laravel API:
Try changing the URL to /api/demo/nope and pressing Run, then Load projects: the catch block shows the 404.
Key takeaways
constby default,letwhen you reassign, template literals for strings with values in them.- Arrow functions are everywhere in the Composition API. Wrap returned object literals in
(). - Destructuring and spread are how Vue code reads API data and updates arrays and objects without mutating them.
map,filter,findandreduceare the building blocks of everycomputed()list.?.and??make templates safe against missing API fields.- Every file is an ES module.
async/awaitwithtry/catch/finallyis the standard shape for loading data.