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)— returnstrueif the value is a ref (e.g., created viaref()).isReactive(value)— returnstrueif the value is a reactive proxy (e.g., fromreactive()orshallowReactive()).isReadonly(value)— returnstrueif the value is a readonly proxy (e.g., fromreadonly()).isProxy(value)— returnstrueif 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, orwatchcan 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 provideoldValueby 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, andwatchoptions. - 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
windowusage 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.prototypereplaced byapp.config.globalProperties.Vue.config.productionTipremoved entirely.destroy()replaced byunmount().v-modelnow 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).