Collection of essential shared Vue Composition Utilities providing foundational building blocks for reactive Vue applications
—
Core utilities for working with Vue's reactivity system, including conversion between refs and reactive objects, and reactive function transformation.
Converts a plain function into a reactive version that automatically unwraps reactive arguments.
/**
* Converts a plain function into reactive version
* @param fn - Function to make reactive
* @param options - Reactify options
* @returns Reactive version of the function
*/
function reactify<T extends Function>(
fn: T,
options?: ReactifyOptions<boolean>
): ReactifyReturn<T>;
interface ReactifyOptions<T extends boolean> {
computedGetter?: T;
}
type ReactifyReturn<T> = T extends (...args: any[]) => any
? (...args: Parameters<T>) => ComputedRef<ReturnType<T>>
: T;Usage Example:
import { reactify, ref } from "@vueuse/shared";
// Original function
const add = (a: number, b: number) => a + b;
// Reactive version
const reactiveAdd = reactify(add);
const a = ref(1);
const b = ref(2);
// Result is a computed ref that updates when a or b change
const sum = reactiveAdd(a, b); // ComputedRef<number>
console.log(sum.value); // 3
a.value = 5;
console.log(sum.value); // 7Applies reactify to every property of an object.
/**
* Applies reactify to every property of an object
* @param obj - Object with functions to reactify
* @param optionsMap - Map of options for each property
* @returns Object with reactive versions of functions
*/
function reactifyObject<T extends Record<string, Function>>(
obj: T,
optionsMap?: ReactifyObjectOptions<T>
): ReactifyObjectReturn<T>;
type ReactifyObjectOptions<T> = {
[K in keyof T]?: ReactifyOptions<boolean>;
};
type ReactifyObjectReturn<T> = {
[K in keyof T]: ReactifyReturn<T[K]>;
};Usage Example:
import { reactifyObject, ref } from "@vueuse/shared";
const math = reactifyObject({
add: (a: number, b: number) => a + b,
multiply: (a: number, b: number) => a * b,
});
const x = ref(3);
const y = ref(4);
const sum = math.add(x, y); // ComputedRef<number>
const product = math.multiply(x, y); // ComputedRef<number>
console.log(sum.value); // 7
console.log(product.value); // 12Converts a ref to a reactive object.
/**
* Converts ref to reactive object
* @param objectRef - Ref containing an object
* @returns Reactive version of the object
*/
function toReactive<T extends Record<string, any>>(
objectRef: MaybeRef<T>
): T;Usage Example:
import { toReactive, ref } from "@vueuse/shared";
const objectRef = ref({ name: 'John', age: 30 });
const reactiveObj = toReactive(objectRef);
// Access properties directly without .value
console.log(reactiveObj.name); // 'John'
reactiveObj.age = 31; // Updates the original refTwo-way synchronization between refs.
/**
* Two-way refs synchronization
* @param left - Left ref to sync
* @param right - Right ref to sync
* @param options - Sync options
* @returns Stop function
*/
function syncRef<L, R>(
left: Ref<L>,
right: Ref<R>,
options?: SyncRefOptions
): () => void;
interface SyncRefOptions {
direction?: 'ltr' | 'rtl' | 'both';
flush?: 'pre' | 'post' | 'sync';
deep?: boolean;
immediate?: boolean;
transform?: {
ltr?: (left: L) => R;
rtl?: (right: R) => L;
};
}Usage Example:
import { syncRef, ref } from "@vueuse/shared";
const left = ref('left');
const right = ref('right');
// Bi-directional sync
const stop = syncRef(left, right);
left.value = 'updated'; // right.value becomes 'updated'
right.value = 'changed'; // left.value becomes 'changed'
// With transformation
const num = ref(0);
const str = ref('0');
syncRef(num, str, {
transform: {
ltr: (num) => num.toString(),
rtl: (str) => parseInt(str, 10)
}
});Keep target ref(s) in sync with a source ref.
/**
* Keep target ref(s) in sync with the source ref
* @param source - Source watch source
* @param targets - Target ref or array of target refs
* @param options - Sync options
* @returns Stop function
*/
function syncRefs<T>(
source: WatchSource<T>,
targets: Ref<T> | Ref<T>[],
options?: SyncRefsOptions
): WatchStopHandle;
interface SyncRefsOptions extends ConfigurableFlushSync {
deep?: boolean;
immediate?: boolean;
}Usage Example:
import { syncRefs, ref } from "@vueuse/shared";
const source = ref('source');
const target1 = ref('');
const target2 = ref('');
const target3 = ref('');
const stop = syncRefs(source, [target1, target2, target3]);
source.value = 'updated'; // All targets become 'updated'
// Single target
const singleTarget = ref('');
syncRefs(source, singleTarget);Computed that returns a reactive object instead of a ref.
/**
* Computed that returns reactive object instead of ref
* @param fn - Computation function
* @returns Reactive object with computed value
*/
function reactiveComputed<T extends Record<string, any>>(fn: () => T): T;Usage Example:
import { reactiveComputed, ref } from "@vueuse/shared";
const name = ref('John');
const age = ref(30);
const user = reactiveComputed(() => ({
fullName: `${name.value} Doe`,
isAdult: age.value >= 18,
info: `${name.value} is ${age.value} years old`
}));
// Access properties directly (no .value needed)
console.log(user.fullName); // 'John Doe'
console.log(user.isAdult); // true
name.value = 'Jane';
console.log(user.fullName); // 'Jane Doe'Reactively omit fields from a reactive object.
/**
* Reactively omit fields from a reactive object
* @param obj - Source object
* @param keys - Keys to omit or predicate function
* @returns Reactive object with omitted fields
*/
function reactiveOmit<T extends object, K extends keyof T>(
obj: T,
...keys: (K | K[])[]
): ReactiveOmitReturn<T, K>;
function reactiveOmit<T extends object>(
obj: T,
predicate: ReactiveOmitPredicate<T>
): ReactiveOmitReturn<T>;
type ReactiveOmitReturn<T extends object, K extends keyof T | undefined = undefined> =
[K] extends [undefined] ? Partial<T> : Omit<T, Extract<K, keyof T>>;
type ReactiveOmitPredicate<T> = (value: T[keyof T], key: keyof T) => boolean;Usage Example:
import { reactiveOmit, reactive } from "@vueuse/shared";
const obj = reactive({
name: 'John',
age: 30,
email: 'john@example.com',
password: 'secret'
});
// Omit specific keys
const publicInfo = reactiveOmit(obj, 'password');
console.log(publicInfo); // { name: 'John', age: 30, email: 'john@example.com' }
// Omit using predicate
const filtered = reactiveOmit(obj, (value, key) => key.includes('pass'));Reactively pick fields from a reactive object.
/**
* Reactively pick fields from a reactive object
* @param obj - Source object
* @param keys - Keys to pick or predicate function
* @returns Reactive object with picked fields
*/
function reactivePick<T extends object, K extends keyof T>(
obj: T,
...keys: (K | K[])[]
): ReactivePickReturn<T, K>;
function reactivePick<T extends object>(
obj: T,
predicate: ReactivePickPredicate<T>
): ReactivePickReturn<T, keyof T>;
type ReactivePickReturn<T extends object, K extends keyof T> = {
[S in K]: UnwrapRef<T[S]>;
};
type ReactivePickPredicate<T> = (value: T[keyof T], key: keyof T) => boolean;Usage Example:
import { reactivePick, reactive } from "@vueuse/shared";
const obj = reactive({
name: 'John',
age: 30,
email: 'john@example.com',
password: 'secret'
});
// Pick specific keys
const publicInfo = reactivePick(obj, 'name', 'email');
console.log(publicInfo); // { name: 'John', email: 'john@example.com' }
// Pick using predicate
const nameFields = reactivePick(obj, (value, key) => key.includes('name'));Install with Tessl CLI
npx tessl i tessl/npm-vueuse--shared