Vue 3 Core Concepts: Proxies, Reactivity Utilities, Composition API, and SSR Explained

const reactiveData = {
  name: 'alice',
  age: 30
};

const handler = {
  get(target, key) {
    console.log(`Accessing property: ${key}`);
    return Reflect.get(target, key);
  },
  set(target, key, value) {
    console.log(`Setting ${key} to ${value}`);
    return Reflect.set(target, key, value);
  },
  deleteProperty(target, key) {
    console.log(`Deleting property: ${key}`);
    return Reflect.deleteProperty(target, key);
  }
};

const proxyInstance = new Proxy(reactiveData, handler);
proxyInstance.name = 'bob'; // Logs: Setting name to bob

Proxy-based reactivity enables fine-grained interception of object operations but requires modern browser support — notably absent in Internet Explorer.

Built-in Reactivity Detection Functions

  • isRef(value) — returns true if the value is a ref (e.g., created via ref()).
  • isReactive(value) — returns true if the value is a reactive proxy (e.g., from reactive() or shallowReactive()).
  • isReadonly(value) — returns true if the value is a readonly proxy (e.g., from readonly()).
  • isProxy(value) — returns true if the value is either a reactive or readonly proxy.

Using setup() Correctly

export default {
  setup(props, { attrs, slots, emit, expose }) {
    // Safe destructuring with reactivity preserved
    const { title } = toRefs(props);
    console.log(title.value); // reactive access

    // Alternative: convert single prop to ref
    const subtitle = toRef(props, 'subtitle');

    // Context usage
    console.log(attrs.class);
    console.log(slots.default?.());
    emit('update:modelValue', 'new-value');
    expose({ reset() { /* public method */ } });

    return { title, subtitle };
  }
};

Avoid direct destructuring of props without toRefs or toRef, as it breaks reactivity.

Composition API vs React Hooks

While both promote logic reuse, Vue’s Composition API has distinct characteristics:

  • No strict call order constraints: ref, computed, or watch can be used inside conditionals, loops, or nested functions.
  • setup() executes once per component instance, unlike React Hooks which run on every render — leading to fewer runtime overheads.
  • Dependency tracking is automatic and internal; no manual dependency arrays are needed for effects like watchEffect.

ref() vs reactive()

Aspect ref() reactive()
Typical use Primitive values, single references Objects and arrays
Access syntax Requires .value in JavaScript (not in templates) Direct property access (obj.prop)
Destructuring Preserves reactivity when destructured from toRefs() Loses reactivity if destructured directly
Underlying mechanism Uses Proxy + get/set traps internally (not Object.defineProperty) Built entirely on Proxy

Note: ref() automatically wraps objects using reactive() under the hood.

watch() vs watchEffect()

// Explicit dependency declaration
watch(
  () => state.count,
  (newVal, oldVal) => {
    console.log(`count changed from ${oldVal} to ${newVal}`);
  },
  { immediate: true }
);

// Automatic dependency collection
const stopWatcher = watchEffect(() => {
  console.log(`Current count: ${state.count}, name: ${state.name}`);
});

// Later, stop watching
stopWatcher();

Key differences:

  • watch() requires explicit source specification and supports old/new value comparison.
  • watchEffect() auto-tracks all reactive dependencies referenced inside its callback. It does not provide oldValue by default and always triggers on initial evaluation.

Composition API Advantages Over Options API

  • Logical concerns (e.g., form validation, data fetching, UI state) can be co-located in composable functions (useForm, useApi), improving maintainability.
  • Reduces scattering of related logic across data, methods, computed, and watch options.
  • Enables better tree-shaking and type inference in TypeScript.

Server-Side Rendering (SSR) Fundamentals

SSR renders the initial HTML on the server before sending it to the client. This contrasts with CSR (Client-Side Rendering), where the browser downloads minimal HTML, then hydrates it with JavaScript.

Benefits:

  • Improved SEO: crawlers receive fully-rendered content immediately.
  • Faster perceived load: avoids blank screen while JS bundles download and execute.

Trade-offs:

  • Increased server complexity and infrastructure requirements.
  • Need for cross-enviroment compatibility (e.g., avoiding window usage in setup code).

Vue 3’s official SSR support is built into vue-server-renderer and integrated with Vite via @vitejs/plugin-vue and @vitejs/plugin-vue-jsx.

Notable Vue 3 Breaking Changes

  • Global APIs moved from Vue.* to app instance methods (app.config, app.component, etc.).
  • Vue.prototype replaced by app.config.globalProperties.
  • Vue.config.productionTip removed entirely.
  • destroy() replaced by unmount().
  • v-model now supports multiple v-model bindings per component using argument syntax (v-model:title, v-model:content).
  • Fragments are supported natively (no need for <template> root wrappers).

Tags: vue3 Reactivity composition-api ssr frontend-interview

Posted on Sun, 17 May 2026 10:14:17 +0000 by saad|_d3vil