diff --git a/packages/shared/index.ts b/packages/shared/index.ts index 5a363a78e3c..0e166d7da97 100644 --- a/packages/shared/index.ts +++ b/packages/shared/index.ts @@ -39,6 +39,7 @@ export * from './useArrayJoin' export * from './useArrayMap' export * from './useArrayReduce' export * from './useArraySome' +export * from './useArrayUnique' export * from './useCounter' export * from './useDateFormat' export * from './useDebounceFn' diff --git a/packages/shared/useArrayUnique/index.md b/packages/shared/useArrayUnique/index.md new file mode 100644 index 00000000000..0d80abbee8b --- /dev/null +++ b/packages/shared/useArrayUnique/index.md @@ -0,0 +1,38 @@ +--- +category: Array +--- + +# useArrayUnique + +reactive unique array + +## Usage + +### Use with array of multiple refs + +```js +import { useArrayUnique } from '@vueuse/core' +const item1 = ref(0) +const item2 = ref(1) +const item3 = ref(1) +const item4 = ref(2) +const item5 = ref(3) +const list = [item1, item2, item3, item4, item5] +const result = useArrayUnique(list) +// result.value: [0, 1, 2, 3] +item5.value = 1 +// result.value: [0, 1, 2] +``` + +### Use with reactive array + +```js +import { useArrayUnique } from '@vueuse/core' + +const list = reactive([1, 2, 2, 3]) +const result = useArrayUnique(list) +// result.value: [1, 2, 3] + +result.value.push(1) +// result.value: [1, 2, 3] +``` diff --git a/packages/shared/useArrayUnique/index.test.ts b/packages/shared/useArrayUnique/index.test.ts new file mode 100644 index 00000000000..948a5fefde5 --- /dev/null +++ b/packages/shared/useArrayUnique/index.test.ts @@ -0,0 +1,29 @@ +import { ref } from 'vue-demi' +import { useArrayUnique } from '../useArrayUnique' + +describe('useArraySome', () => { + it('should be defined', () => { + expect(useArrayUnique).toBeDefined() + }) + + it('should work with array of refs', () => { + const item1 = ref(0) + const item2 = ref(1) + const item3 = ref(1) + const item4 = ref(2) + const item5 = ref(3) + const list = [item1, item2, item3, item4, item5] + const result = useArrayUnique(list) + expect(result.value.length).toBe(4) + item5.value = 2 + expect(result.value.length).toBe(3) + }) + + it('should work with reactive array', () => { + const list = ref([1, 2, 2, 3]) + const result = useArrayUnique(list) + expect(result.value.length).toBe(3) + list.value.push(1) + expect(result.value.length).toBe(3) + }) +}) diff --git a/packages/shared/useArrayUnique/index.ts b/packages/shared/useArrayUnique/index.ts new file mode 100644 index 00000000000..0d313fdf907 --- /dev/null +++ b/packages/shared/useArrayUnique/index.ts @@ -0,0 +1,15 @@ +import type { ComputedRef } from 'vue-demi' +import { computed } from 'vue-demi' +import type { MaybeComputedRef } from '../utils' +import { resolveUnref } from '../resolveUnref' + +/** + * reactive unique array + * @see https://vueuse.org/useArrayUnique + * @param {Array} list - the array was called upon. + * @returns {Array} A computed ref that returns a unique array of items. + */ +export function useArrayUnique( + list: MaybeComputedRef[]>): ComputedRef { + return computed(() => [...new Set(resolveUnref(list).map(element => resolveUnref(element)))]) +}