Skip to content
Vue.js API Reference & Cheatsheet

Vue.js API Reference & Cheatsheet

DodaTech Updated Jun 6, 2026 10 min read

Vue.js is a progressive JavaScript framework — this reference covers every directive, API, lifecycle hook, and built-in component you need for production Vue 3 apps.

What You’ll Learn

  • All Vue directives with shorthands and modifiers
  • Options API vs Composition API side-by-side
  • Built-in components (Transition, KeepAlive, Teleport, Suspense)
  • Pinia store setup and Vue Router configuration
  • Template refs, render functions, and custom directives
  • Global API and error handling patterns

Why This Reference Matters

When you’re building a Vue app, you don’t want to dig through 10 browser tabs to remember how v-model.lazy or onErrorCaptured works. This reference is your single source of truth — everything in one place.

Security note: Understanding Reference helps build more secure applications — a core principle at DodaTech, where tools like Durga Antivirus Pro and Doda Browser rely on solid implementation practices.

At DodaTech, our teams use this exact reference when building dashboard panels for Durga Antivirus Pro, file management views in DodaZIP, and settings pages in Doda Browser. Having a consolidated API reference speeds up development and reduces bugs.

Vue Curriculum — Where Reference Fits

    flowchart LR
  A[Vue Basics] --> B[Vue Components]
  B --> C[Vue Router]
  C --> D[Vue Advanced]
  D --> E[Vue Reference]
  E:::current

  classDef current fill:#42b883,color:#fff,stroke:#3aa876,stroke-width:2px
  

Installation

npm create vite@latest my-app -- --template vue
cd my-app && npm install && npm run dev
npm install vue-router@4 pinia

Directives

DirectiveShorthandPurpose
v-bind:Bind attribute to expression
v-modelTwo-way data binding
v-ifConditional render (remove/add DOM)
v-else-ifElse-if condition
v-elseElse condition
v-showToggle CSS display
v-forList rendering
v-on@Event binding
v-onceRender once
v-memoMemoize template fragment
v-cloakHide until compiled
v-preSkip compilation
v-htmlRaw HTML (XSS risk)
v-textText content
v-slot#Named/scoped slots

Directive Modifiers

@click.stop          <!-- stopPropagation  stops event from bubbling up -->
@click.prevent       <!-- preventDefault  prevents form submission, etc. -->
@click.once          <!-- fire once  event listener removed after first click -->
@keyup.enter         <!-- key alias  fires only on Enter key -->
@keyup.ctrl.enter    <!-- modifier + key  Ctrl+Enter combination -->

v-model.lazy         <!-- sync on change instead of keystroke -->
v-model.number       <!-- coerce input to number type -->
v-model.trim         <!-- trim leading/trailing whitespace -->

Options API

export default {
  name: "ComponentName",
  components: {},               // Local component registration
  props: {                      // Props: parent → child data
    title: String,
    count: { type: Number, default: 0 }
  },
  emits: ["update", "delete"],  // Declared events the component fires
  data() { return { msg: "Hello" }; },  // Reactive state (must be function)
  computed: {                   // Cached derived values
    reversed() { return this.msg.split("").reverse().join(""); }
  },
  watch: {                      // Side effects on data changes
    count(n, o) { /* n = new value, o = old value */ }
  },
  methods: {                    // Functions attached to the component
    handleClick() { this.count++; }
  },
  // Lifecycle — runs in this order:
  beforeCreate() {},            // Instance initialized, nothing reactive yet
  created() {},                 // Reactive data ready, no DOM
  beforeMount() {},             // About to render
  mounted() {},                 // DOM in page — safe for API calls
  beforeUpdate() {},            // Data changed, about to re-render
  updated() {},                 // DOM re-rendered
  beforeUnmount() {},           // About to destroy component
  unmounted() {},               // Cleanup timers, listeners
  errorCaptured(err, instance, info) {},  // Catches child errors
};

Composition API (<script setup>)

<script setup>
// All imports are available directly — no export default needed
import { ref, reactive, computed, watch, onMounted, provide, inject, nextTick } from "vue";

const count = ref(0);                // ref() wraps any value, use .value in script
const state = reactive({ key: "value" });  // reactive() for objects, no .value
const double = computed(() => count.value * 2);  // Computed: caches until deps change
watch(count, (n, o) => {});          // Watcher: runs function on change
onMounted(() => {});                 // Lifecycle: onMounted, onUnmounted, etc.

provide("key", value);               // Provide data to all descendants
const val = inject("key", "default"); // Inject data from ancestor

await nextTick();                    // Wait for DOM update after state change

// Async setup — works inside Suspense
const data = await fetch("/api/data").then(r => r.json());
</script>

Ref vs Reactive

const a = ref(0);           // primitive → a.value to read/write
const b = ref({});          // object → b.value.key
const c = reactive({});     // object → c.key (no .value)

Built-in Components

ComponentPurposeWhen to Use
<component :is="..." />Dynamic component vending machineTab switching
<slot />Content outletLayout components
<Transition>Animate enter/leaveSingle element animations
<TransitionGroup>Animate list itemsList reorder/add/remove
<KeepAlive>Cache dynamic componentsPreserve form state across tabs
<Teleport to="...">Render elsewhere in DOMModals, tooltips
<Suspense>Handle async depsLoading states for async components
<RouterLink>Navigation linkSPA routing
<RouterView>Route outletWhere matched route renders

Lifecycle Hooks

Options API          Composition API
─────────────────────────────────────
beforeCreate         setup()           ← component initialized
created              setup()           ← reactive state ready
beforeMount          onBeforeMount     ← about to render
mounted              onMounted         ← DOM is in page ✅ fetch data here
beforeUpdate         onBeforeUpdate    ← data changed, re-render pending
updated              onUpdated         ← DOM re-rendered
beforeUnmount        onBeforeUnmount   ← about to destroy
unmounted            onUnmounted       ← cleanup timers/listeners
errorCaptured        onErrorCaptured   ← catch child errors
activated            onActivated       ← KeepAlive — component re-activated
deactivated          onDeactivated     ← KeepAlive — component deactivated

Vue Router

import { createRouter, createWebHistory } from "vue-router";

const router = createRouter({
  history: createWebHistory(),   // Clean URLs without #
  routes: [
    { path: "/", component: Home },
    { path: "/:pathMatch(.*)*", component: NotFound }  // Catch-all 404
  ],
  scrollBehavior() { return { top: 0 }; }  // Scroll to top on navigation
});

// In component:
this.$router.push("/path");       // Navigate (adds history entry)
this.$router.replace("/path");    // Navigate (replaces current entry)
this.$router.go(-1);              // Back one step
this.$route.params.id;            // Route parameter
this.$route.query.search;         // Query string (?search=...)

Navigation Guards

router.beforeEach((to, from) => {});   // Global — runs on every route
router.afterEach((to, from) => {});    // Global — runs after navigation
// Per-route: beforeEnter in route config
// In-component: beforeRouteEnter, beforeRouteUpdate, beforeRouteLeave

Pinia

import { defineStore } from "pinia";
import { ref, computed } from "vue";

export const useStore = defineStore("name", () => {
  const state = ref(initialValue);
  const getter = computed(() => state.value * 2);
  function action() { state.value++; }
  return { state, getter, action };
});

// In component:
const store = useStore();
store.state;          // read
store.state++;        // mutate (allowed directly in Pinia)
store.action();       // call action

Template Refs

<input ref="input" />
<p v-for="item in list" :ref="setItemRef" />
// Options API
this.$refs.input.focus();

// Composition API
const input = ref(null);    // ref name must match template ref name
onMounted(() => input.value?.focus());

Class & Style Bindings

<div :class="{ active: isActive, 'text-danger': hasError }" />
<div :class="[baseClass, activeClass]" />
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }" />
<div :style="[baseStyles, overrides]" />

Render Function

import { h } from "vue";
h("div", { class: "box", style: { color: "red" } }, [
  h("h1", "Title"),
  h("p", "Content")
]);

Custom Directive

app.directive("highlight", {
  mounted(el, binding) { el.style.background = binding.value; },
  updated(el, binding) { el.style.background = binding.value; }
});

Global API

const app = createApp(App);
app.component("name", Comp);             // Register global component
app.directive("name", directive);         // Register global directive
app.use(plugin);                          // Install plugin (router, pinia)
app.provide("key", value);                // Provide data globally
app.config.errorHandler = (err, instance, info) => {};  // Global error handler
app.config.globalProperties.$api = axios;  // Make available in all components

Common Mistakes

1. Using v-html with user input

v-html renders raw HTML. If the content comes from users, attackers can inject <script> tags. Only use v-html with trusted content from your server.

2. Forgetting that data must be a function

// ❌ Bad — all instances share the same state
data: { count: 0 }

// ✅ Correct — each instance gets its own copy
data() { return { count: 0 }; }

3. Confusing Options API and Composition API lifecycle names

mounted() in Options becomes onMounted() in Composition API. The on prefix is easy to forget.

4. Mutating Pinia state outside of actions

Pinia allows direct mutations in templates, but for complex logic always use actions — it makes debugging far easier when you can trace who changed what.

5. Not handling NavigationDuplicated errors

// router.push throws if you navigate to the current route
try {
  await router.push("/same-page");
} catch (e) {
  if (e.name !== "NavigationDuplicated") throw e;
}

6. Forgetting :key with v-for in <TransitionGroup>

Without unique keys, Vue can’t track which items entered, left, or moved — animations break silently.

Practice Questions

1. What’s the shorthand for v-bind and v-on? v-bind:, v-on@. Example: :src="url" and @click="handler".

2. How do you make a route parameter available as a component prop? Set props: true in the route definition. The param (e.g., :id) becomes a prop on the component.

3. What’s the difference between mounted (Options) and onMounted (Composition)? They do the same thing but have different names. Options uses mounted(), Composition uses onMounted(() => {}).

4. When would you use shallowRef instead of ref? When you have large data that doesn’t need deep reactivity — like a static array of thousands of items. shallowRef only tracks .value assignment, not nested changes.

5. How do you catch errors in child components? Use errorCaptured (Options) or onErrorCaptured (Composition). Return false to prevent the error from propagating upward.

Challenge: Open your browser console on any Vue app and inspect __vue_app__ on the root element. Explore the component tree, reactive state, and available methods. This is a powerful debugging technique.

FAQ

What is the difference between ref and reactive?
ref holds any value (primitives included) and requires .value in script context. reactive only accepts objects and provides direct property access without .value.
How do I register a component globally?
Use app.component(‘MyComponent’, MyComponent) in main.js. The component is then available everywhere without importing.
When should I use KeepAlive?
When switching between dynamic components (tabs, views) that have form input, loaded data, or complex state you don’t want destroyed.
What is the catch-all route pattern?
{ path: ‘/:pathMatch(.)’, component: NotFound }. The (.) captures any unmatched path, and it must be the last route.
How do I provide/inject reactive data?
Use provide(‘key’, ref(‘value’)) to pass a ref. The descendant receives the same ref — changes propagate reactively.
What does nextTick do?
It waits for Vue to finish updating the DOM after a reactive state change. Use it when you need to measure or interact with updated DOM elements.

Try It Yourself

Copy this into a new HTML file and open it in your browser:

<!DOCTYPE html>
<html>
<head>
  <title>Vue Reference Sandbox</title>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <style>
    body { font-family: sans-serif; max-width: 600px; margin: 40px auto; padding: 0 20px; }
    .demo-box { border: 2px dashed #42b883; padding: 16px; border-radius: 8px; margin: 12px 0; }
    input, button { padding: 8px; margin: 4px; border: 1px solid #ddd; border-radius: 4px; }
    button { background: #42b883; color: white; cursor: pointer; }
    .active { background: #e8f5e9; }
  </style>
</head>
<body>
  <div id="app">
    <h1>Vue Reference Playground</h1>

    <div class="demo-box">
      <h3>v-model + computed</h3>
      <input v-model="name" placeholder="Enter name">
      <p>Uppercase: <strong>{{ upperName }}</strong></p>
    </div>

    <div class="demo-box">
      <h3>v-if / v-show</h3>
      <button @click="show = !show">Toggle</button>
      <p v-if="show">v-if: I appear/disappear from DOM</p>
      <p v-show="show">v-show: I'm hidden with CSS</p>
    </div>

    <div class="demo-box">
      <h3>v-for with :key</h3>
      <input v-model="newItem" @keyup.enter="addItem" placeholder="Add item">
      <button @click="addItem">Add</button>
      <ul>
        <li v-for="(item, i) in items" :key="i">
          {{ item }} <button @click="items.splice(i, 1)"></button>
        </li>
      </ul>
    </div>
  </div>

  <script>
    const { createApp, ref, computed } = Vue;
    createApp({
      setup() {
        const name = ref("Vue");
        const upperName = computed(() => name.value.toUpperCase());
        const show = ref(true);
        const items = ref(["Directive", "Component", "Reactivity"]);
        const newItem = ref("");

        function addItem() {
          if (newItem.value.trim()) {
            items.value.push(newItem.value.trim());
            newItem.value = "";
          }
        }

        return { name, upperName, show, items, newItem, addItem };
      }
    }).mount("#app");
  </script>
</body>
</html>

What to try: Type in the input and watch the uppercase version update live. Toggle the visibility buttons. Add and remove items from the list. All these use core Vue directives you’ve learned.

What’s Next

ResourceDescription
https://tutorials.dodatech.com/frameworks/vue/vue-advanced/Composition API, Pinia, advanced patterns
JavaScriptMaster modern JavaScript fundamentals
TypeScriptAdd type safety to your Vue apps
Node.jsBuild backends for your Vue SPAs
ReactCompare Vue with React for your next project

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro