Sanakey
3 天以前 b5c1614fe473330ceca8b7cff0f1802e19bd5039
提交 | 用户 | age
7ca007 1 import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router';
9c43c7 2 import type { App, Component } from 'vue';
55e9d9 3
c516d3 4 import { intersectionWith, isEqual, mergeWith, unionWith } from 'lodash-es';
a305e5 5 import { unref } from 'vue';
4d2fb0 6 import { isArray, isObject } from '@/utils/is';
e12c58 7
35d2bf 8 export const noop = () => {};
8a9ca4 9
2f6253 10 /**
11  * @description:  Set ui mount node
12  */
13 export function getPopupContainer(node?: HTMLElement): HTMLElement {
116a1f 14   return (node?.parentNode as HTMLElement) ?? document.body;
2f6253 15 }
ba068b 16
2f6253 17 /**
18  * Add the object as a parameter to the URL
19  * @param baseUrl url
20  * @param obj
21  * @returns {string}
22  * eg:
23  *  let obj = {a: '3', b: '4'}
24  *  setObjToUrlParams('www.baidu.com', obj)
25  *  ==>www.baidu.com?a=3&b=4
26  */
27 export function setObjToUrlParams(baseUrl: string, obj: any): string {
28   let parameters = '';
29   for (const key in obj) {
30     parameters += key + '=' + encodeURIComponent(obj[key]) + '&';
31   }
32   parameters = parameters.replace(/&$/, '');
da0491 33   return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters;
2f6253 34 }
35
4c63b1 36 /**
c516d3 37  * Recursively merge two objects.
KL 38  * 递归合并两个对象。
39  *
40  * @param source The source object to merge from. 要合并的源对象。
41  * @param target The target object to merge into. 目标对象,合并后结果存放于此。
42  * @param mergeArrays How to merge arrays. Default is "replace".
43  *        如何合并数组。默认为replace。
44  *        - "union": Union the arrays. 对数组执行并集操作。
45  *        - "intersection": Intersect the arrays. 对数组执行交集操作。
46  *        - "concat": Concatenate the arrays. 连接数组。
47  *        - "replace": Replace the source array with the target array. 用目标数组替换源数组。
48  * @returns The merged object. 合并后的对象。
4c63b1 49  */
KL 50 export function deepMerge<T extends object | null | undefined, U extends object | null | undefined>(
c516d3 51   source: T,
KL 52   target: U,
53   mergeArrays: 'union' | 'intersection' | 'concat' | 'replace' = 'replace',
4c63b1 54 ): T & U {
c516d3 55   if (!target) {
KL 56     return source as T & U;
57   }
58   if (!source) {
59     return target as T & U;
60   }
7535db 61   return mergeWith({}, source, target, (sourceValue, targetValue) => {
KL 62     if (isArray(targetValue) && isArray(sourceValue)) {
63       switch (mergeArrays) {
64         case 'union':
65           return unionWith(sourceValue, targetValue, isEqual);
66         case 'intersection':
67           return intersectionWith(sourceValue, targetValue, isEqual);
68         case 'concat':
69           return sourceValue.concat(targetValue);
70         case 'replace':
71           return targetValue;
72         default:
73           throw new Error(`Unknown merge array strategy: ${mergeArrays as string}`);
74       }
4c63b1 75     }
7535db 76     if (isObject(targetValue) && isObject(sourceValue)) {
KL 77       return deepMerge(sourceValue, targetValue, mergeArrays);
78     }
79     return undefined;
80   });
2f6253 81 }
82
ba068b 83 export function openWindow(
V 84   url: string,
56a966 85   opt?: { target?: TargetContext | string; noopener?: boolean; noreferrer?: boolean },
ba068b 86 ) {
V 87   const { target = '__blank', noopener = true, noreferrer = true } = opt || {};
88   const feature: string[] = [];
89
90   noopener && feature.push('noopener=yes');
91   noreferrer && feature.push('noreferrer=yes');
92
93   window.open(url, target, feature.join(','));
94 }
a305e5 95
V 96 // dynamic use hook props
92cc60 97 export function getDynamicProps<T extends Record<string, unknown>, U>(props: T): Partial<U> {
a305e5 98   const ret: Recordable = {};
V 99
05030e 100   Object.keys(props).forEach((key) => {
a305e5 101     ret[key] = unref((props as Recordable)[key]);
V 102   });
103
104   return ret as Partial<U>;
144ab5 105 }
581007 106
e12c58 107 export function getRawRoute(route: RouteLocationNormalized): RouteLocationNormalized {
V 108   if (!route) return route;
109   const { matched, ...opt } = route;
110   return {
111     ...opt,
112     matched: (matched
113       ? matched.map((item) => ({
114           meta: item.meta,
115           name: item.name,
116           path: item.path,
117         }))
118       : undefined) as RouteRecordNormalized[],
119   };
120 }
55e9d9 121
92cc60 122 // https://github.com/vant-ui/vant/issues/8302
L 123 type EventShim = {
124   new (...args: any[]): {
125     $props: {
126       onClick?: (...args: any[]) => void;
127     };
128   };
129 };
130
131 export type WithInstall<T> = T & {
132   install(app: App): void;
133 } & EventShim;
134
135 export type CustomComponent = Component & { displayName?: string };
136
137 export const withInstall = <T extends CustomComponent>(component: T, alias?: string) => {
138   (component as Record<string, unknown>).install = (app: App) => {
139     const compName = component.name || component.displayName;
140     if (!compName) return;
141     app.component(compName, component);
55e9d9 142     if (alias) {
V 143       app.config.globalProperties[alias] = component;
144     }
145   };
92cc60 146   return component as WithInstall<T>;
55e9d9 147 };