From 08d7738f6810e7f22653224d6b2c40a41f2ce31f Mon Sep 17 00:00:00 2001 From: xingyu Date: Sat, 10 Jun 2023 12:17:22 +0800 Subject: [PATCH] fix(deepMerge): the default merge strategy --- src/utils/index.ts | 55 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 13 deletions(-) diff --git a/src/utils/index.ts b/src/utils/index.ts index 58b5a38..9726cfa 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,7 +1,7 @@ import type { App, Component } from 'vue' import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router' -import { cloneDeep, mergeWith, uniq } from 'lodash-es' +import { intersectionWith, isEqual, mergeWith, unionWith } from 'lodash-es' import { unref } from 'vue' import { isArray, isObject } from '@/utils/is' @@ -34,21 +34,50 @@ export function setObjToUrlParams(baseUrl: string, obj: any): string { } /** - * 递归合并两个对象。 * Recursively merge two objects. - * @param target 目标对象,合并后结果存放于此。The target object to merge into. - * @param source 要合并的源对象。The source object to merge from. - * @returns 合并后的对象。The merged object. + * 递归合并两个对象。 + * + * @param source The source object to merge from. 要合并的源对象。 + * @param target The target object to merge into. 目标对象,合并后结果存放于此。 + * @param mergeArrays How to merge arrays. Default is "replace". + * 如何合并数组。默认为replace。 + * - "union": Union the arrays. 对数组执行并集操作。 + * - "intersection": Intersect the arrays. 对数组执行交集操作。 + * - "concat": Concatenate the arrays. 连接数组。 + * - "replace": Replace the source array with the target array. 用目标数组替换源数组。 + * @returns The merged object. 合并后的对象。 */ -export function deepMerge(target: T, source: U): T & U { - return mergeWith(cloneDeep(target), source, (objValue, srcValue) => { - if (isObject(objValue) && isObject(srcValue)) { - return mergeWith(cloneDeep(objValue), srcValue, (prevValue, nextValue) => { - // 如果是数组,合并数组(去重) If it is an array, merge the array (remove duplicates) - return isArray(prevValue) ? uniq(prevValue, nextValue) : undefined - }) +export function deepMerge( + source: T, + target: U, + mergeArrays: 'union' | 'intersection' | 'concat' | 'replace' = 'replace' +): T & U { + if (!target) { + return source as T & U + } + if (!source) { + return target as T & U + } + if (isArray(target) && isArray(source)) { + switch (mergeArrays) { + case 'union': + return unionWith(target, source, isEqual) as T & U + case 'intersection': + return intersectionWith(target, source, isEqual) as T & U + case 'concat': + return target.concat(source) as T & U + case 'replace': + return source as T & U + default: + throw new Error(`Unknown merge array strategy: ${mergeArrays}`) } - }) + } + if (isObject(target) && isObject(source)) { + return mergeWith({}, target, source, (targetValue, sourceValue) => { + return deepMerge(targetValue, sourceValue, mergeArrays) + }) as T & U + } + return source as T & U } export function openWindow(url: string, opt?: { target?: TargetContext | string; noopener?: boolean; noreferrer?: boolean }) {