1
0
mirror of https://github.com/robonen/tools.git synced 2026-03-20 10:54:44 +00:00

feat(packages/vue): add useSyncRefs composable

This commit is contained in:
2024-05-31 01:15:30 +07:00
parent d7c32f2f45
commit 107e192b33
2 changed files with 83 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
import { describe, expect, it } from 'vitest';
import { ref } from 'vue';
import { useSyncRefs } from '.';
describe('useSyncRefs', () => {
it('sync the value of a source ref with multiple target refs', () => {
const source = ref(0);
const target1 = ref(0);
const target2 = ref(0);
useSyncRefs(source, [target1, target2]);
source.value = 10;
expect(target1.value).toBe(10);
expect(target2.value).toBe(10);
});
it('sync the value of a source ref with a single target ref', () => {
const source = ref(0);
const target = ref(0);
useSyncRefs(source, target);
source.value = 20;
expect(target.value).toBe(20);
});
it('stop watching when the stop handle is called', () => {
const source = ref(0);
const target = ref(0);
const stop = useSyncRefs(source, target);
source.value = 30;
stop();
source.value = 40;
expect(target.value).toBe(30);
});
});

View File

@@ -0,0 +1,44 @@
import { watch, type Ref, type WatchOptions, type WatchSource } from 'vue';
import { isArray } from '@robonen/stdlib';
/**
* @name useSyncRefs
* @category Reactivity
* @description Syncs the value of a source ref with multiple target refs
*
* @param {WatchSource<T>} source Source ref to sync
* @param {Ref<T> | Ref<T>[]} targets Target refs to sync
* @param {WatchOptions} watchOptions Watch options
* @returns {WatchStopHandle} Watch stop handle
*
* @example
* const source = ref(0);
* const target1 = ref(0);
* const target2 = ref(0);
* useSyncRefs(source, [target1, target2]);
*
* @example
* const source = ref(0);
* const target1 = ref(0);
* useSyncRefs(source, target1, { immediate: true });
*/
export function useSyncRefs<T = unknown>(
source: WatchSource<T>,
targets: Ref<T> | Ref<T>[],
watchOptions: WatchOptions = {},
) {
const {
flush = 'sync',
deep = false,
immediate = true,
} = watchOptions;
if (!isArray(targets))
targets = [targets];
return watch(
source,
(value) => targets.forEach((target) => target.value = value),
{ flush, deep, immediate },
);
}