Vue's reactivity system provides fine-grained reactive state management with automatic dependency tracking. Built on ES6 Proxies, it offers superior performance and developer experience compared to Vue 2's Object.defineProperty approach.
Creates a reactive reference that can hold any value type with automatic unwrapping in templates.
/**
* Creates a reactive reference to a value
* @param value - Initial value
* @returns Reactive reference with .value property
*/
function ref<T>(value: T): Ref<UnwrapRef<T>>;
function ref<T = any>(): Ref<T | undefined>;
interface Ref<T = any> {
value: T;
}
type UnwrapRef<T> = T extends Ref<infer V> ? UnwrapRef<V> : T;Usage Examples:
import { ref } from "vue";
// Primitive values
const count = ref(0);
const message = ref("Hello");
const isActive = ref(true);
// Objects and arrays (deeply reactive)
const user = ref({ name: "John", age: 30 });
const items = ref([1, 2, 3]);
// Access/modify values
console.log(count.value); // 0
count.value = 10;
user.value.name = "Jane";Creates a reactive proxy of an object with deep reactivity for nested properties.
/**
* Creates a reactive proxy of an object
* @param target - Plain object to make reactive
* @returns Reactive proxy with all nested properties reactive
*/
function reactive<T extends object>(target: T): UnwrapNestedRefs<T>;Usage Examples:
import { reactive } from "vue";
// Simple object
const state = reactive({
count: 0,
message: "Hello"
});
// Nested objects (deeply reactive)
const user = reactive({
profile: {
name: "John",
settings: {
theme: "dark"
}
}
});
// Direct property access (no .value needed)
state.count++; // Reactive
user.profile.name = "Jane"; // Reactive
user.profile.settings.theme = "light"; // ReactiveCreates a readonly proxy that prevents modifications while maintaining reactivity for reading.
/**
* Creates a readonly proxy of an object or ref
* @param target - Object to make readonly
* @returns Readonly proxy that throws on write attempts
*/
function readonly<T>(target: T): DeepReadonly<T>;Creates shallow reactive proxies that only track changes to top-level properties.
/**
* Creates a shallow reactive proxy (only root-level properties are reactive)
* @param target - Object to make shallow reactive
* @returns Shallow reactive proxy
*/
function shallowReactive<T extends object>(target: T): T;
/**
* Creates a shallow ref (only .value is reactive, not nested properties)
* @param value - Initial value
* @returns Shallow reactive reference
*/
function shallowRef<T>(value: T): ShallowRef<T>;
/**
* Creates a shallow readonly proxy
* @param target - Object to make shallow readonly
* @returns Shallow readonly proxy
*/
function shallowReadonly<T>(target: T): Readonly<T>;
interface ShallowRef<T = any> {
value: T;
}/**
* Gets the underlying value from a ref or returns the value if not a ref
* @param val - Ref or plain value
* @returns Underlying value
*/
function unref<T>(val: T | Ref<T>): T;
/**
* Converts a property of a reactive object to a ref
* @param object - Reactive object
* @param key - Property key
* @returns Ref linked to the property
*/
function toRef<T extends object, K extends keyof T>(object: T, key: K): ToRef<T[K]>;
/**
* Converts all properties of an object to refs
* @param object - Object to convert
* @returns Object with all properties as refs
*/
function toRefs<T extends object>(object: T): ToRefs<T>;
/**
* Gets the underlying value from ref, computed, or function
* @param val - Ref, computed, function, or plain value
* @returns Resolved value
*/
function toValue<T>(val: T | Ref<T> | (() => T)): T;/**
* Checks if a value is a ref
* @param val - Value to check
* @returns True if value is a ref
*/
function isRef<T>(val: Ref<T> | unknown): val is Ref<T>;
/**
* Checks if a value is a reactive proxy
* @param value - Value to check
* @returns True if value is reactive
*/
function isReactive(value: unknown): boolean;
/**
* Checks if a value is a readonly proxy
* @param value - Value to check
* @returns True if value is readonly
*/
function isReadonly(value: unknown): boolean;
/**
* Checks if a value is a proxy (reactive or readonly)
* @param value - Value to check
* @returns True if value is a proxy
*/
function isProxy(value: unknown): boolean;
/**
* Checks if a reactive value is shallow
* @param value - Value to check
* @returns True if value is shallow reactive
*/
function isShallow(value: unknown): boolean;/**
* Marks an object to never be made reactive
* @param value - Object to mark as raw
* @returns Same object marked as raw
*/
function markRaw<T>(value: T): T;
/**
* Gets the original object from a reactive proxy
* @param observed - Reactive proxy
* @returns Original non-reactive object
*/
function toRaw<T>(observed: T): T;
/**
* Converts a value to reactive proxy
* @param value - Value to convert
* @returns Reactive proxy or original value
*/
function toReactive<T>(value: T): T;
/**
* Converts a value to readonly proxy
* @param value - Value to convert
* @returns Readonly proxy or original value
*/
function toReadonly<T>(value: T): T;Create refs with custom getter/setter logic and dependency tracking.
/**
* Creates a custom ref with explicit dependency tracking control
* @param factory - Factory function that returns getter/setter
* @returns Custom ref instance
*/
function customRef<T>(factory: CustomRefFactory<T>): Ref<T>;
type CustomRefFactory<T> = (
track: () => void,
trigger: () => void
) => {
get: () => T;
set: (value: T) => void;
};Usage Example:
import { customRef } from "vue";
function useDebouncedRef(value, delay = 200) {
let timeout;
return customRef((track, trigger) => {
return {
get() {
track(); // Track dependency
return value;
},
set(newValue) {
clearTimeout(timeout);
timeout = setTimeout(() => {
value = newValue;
trigger(); // Trigger updates
}, delay);
}
};
});
}/**
* Manually triggers updates for a shallow ref
* @param ref - Shallow ref to trigger
*/
function triggerRef(ref: ShallowRef): void;
/**
* Creates a proxy that unwraps refs automatically
* @param objectWithRefs - Object containing refs
* @returns Proxy that unwraps refs on access
*/
function proxyRefs<T extends object>(objectWithRefs: T): ShallowUnwrapRef<T>;/**
* Creates a computed ref that reactively computes based on dependencies
* @param getter - Function that computes the value
* @returns Readonly computed ref
*/
function computed<T>(getter: () => T): ComputedRef<T>;
/**
* Creates a writable computed ref with getter and setter
* @param options - Object with get and set functions
* @returns Writable computed ref
*/
function computed<T>(options: {
get: () => T;
set: (value: T) => void;
}): WritableComputedRef<T>;
interface ComputedRef<T = any> extends WritableComputedRef<T> {
readonly value: T;
}
interface WritableComputedRef<T> extends Ref<T> {
readonly effect: ReactiveEffect<T>;
}Usage Examples:
import { ref, computed } from "vue";
const count = ref(0);
// Read-only computed
const doubled = computed(() => count.value * 2);
// Writable computed
const fullName = computed({
get() {
return `${firstName.value} ${lastName.value}`;
},
set(newValue) {
[firstName.value, lastName.value] = newValue.split(" ");
}
});/**
* Creates a reactive effect that runs when dependencies change
* @param fn - Effect function
* @param options - Effect options
* @returns ReactiveEffect instance
*/
function effect<T = any>(
fn: () => T,
options?: ReactiveEffectOptions
): ReactiveEffect<T>;
/**
* Stops a reactive effect
* @param effect - Effect to stop
*/
function stop(effect: ReactiveEffect): void;
interface ReactiveEffectOptions {
lazy?: boolean;
scheduler?: (job: EffectScheduler) => void;
scope?: EffectScope;
allowRecurse?: boolean;
onStop?: () => void;
}
class ReactiveEffect<T = any> {
constructor(
public fn: () => T,
public scheduler: EffectScheduler | null = null,
scope?: EffectScope
);
run(): T;
stop(): void;
}/**
* Gets the currently running watcher/effect
* @returns Current watcher instance or null
*/
function getCurrentWatcher(): ReactiveEffect | null;
/**
* Registers a cleanup callback for the current watcher
* @param cleanupFn - Function to call on cleanup
*/
function onWatcherCleanup(cleanupFn: () => void): void;
/**
* Registers a cleanup callback for the current effect
* @param cleanupFn - Function to call on cleanup
*/
function onEffectCleanup(cleanupFn: () => void): void;
/**
* Enable reactivity tracking globally
*/
function enableTracking(): void;
/**
* Pause reactivity tracking temporarily
*/
function pauseTracking(): void;
/**
* Reset tracking state to previous level
*/
function resetTracking(): void;Collect and manage multiple effects for batch disposal.
/**
* Creates a new effect scope
* @param detached - Whether scope is detached from parent
* @returns EffectScope instance
*/
function effectScope(detached?: boolean): EffectScope;
/**
* Gets the current active effect scope
* @returns Current scope or undefined
*/
function getCurrentScope(): EffectScope | undefined;
/**
* Registers a disposal callback for current scope
* @param fn - Disposal callback
*/
function onScopeDispose(fn: () => void): void;
class EffectScope {
run<T>(fn: () => T): T | undefined;
stop(): void;
}Usage Example:
import { effectScope, ref, computed } from "vue";
const scope = effectScope();
scope.run(() => {
const count = ref(0);
const doubled = computed(() => count.value * 2);
// Effects are collected in scope
});
// Stop all effects in scope
scope.stop();type Ref<T = any> = {
value: T;
[RefSymbol]: true;
};
type ShallowRef<T = any> = {
value: T;
[RefSymbol]: true;
[ShallowRefMarker]: true;
};
type ComputedRef<T = any> = {
readonly value: T;
[RefSymbol]: true;
} & ComputedRefImpl<T>;
type UnwrapNestedRefs<T> = T extends Ref ? T : UnwrapRefSimple<T>;
type ToRef<T> = T extends Ref ? T : Ref<T>;
type ToRefs<T = any> = {
[K in keyof T]: ToRef<T[K]>;
};
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P];
};