forked from mengyxu/noob-components
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
3.8 KiB
171 lines
3.8 KiB
|
3 months ago
|
# Utilities
|
||
|
|
|
||
|
|
> Utility functions for async operations and object manipulation.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
This directory contains utility modules:
|
||
|
|
- `asyncUtil.ts` - Promise-based async event handling
|
||
|
|
- `objectUtil.ts` - Object manipulation helpers
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Async Utilities
|
||
|
|
|
||
|
|
**File**: `/home/hechang27/Documents/sprt/noob-components/plugs/util/asyncUtil.ts`
|
||
|
|
|
||
|
|
### useAsyncEmits
|
||
|
|
|
||
|
|
Creates a promise-based wrapper around Vue component emit functions.
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export function useAsyncEmits<Emits extends Record<string, any[]>>(emits: (evt: any, ...args: any[]) => void) {
|
||
|
|
const emitsAsync = <Evt extends keyof Emits>(evt: Evt, ...args: ExtractArgs<Emits[Evt]>) =>
|
||
|
|
new Promise<ExtractResult<Emits[Evt]>>((resolve, reject) => {
|
||
|
|
emits(evt, { resolve, reject }, ...args);
|
||
|
|
});
|
||
|
|
|
||
|
|
return emitsAsync;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Type Parameters
|
||
|
|
|
||
|
|
| Parameter | Description |
|
||
|
|
|-----------|-------------|
|
||
|
|
| `Emits` | Record of event names to argument tuple types |
|
||
|
|
|
||
|
|
#### Handler Type
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export type AsyncHandler<T> = {
|
||
|
|
resolve: (t: T | PromiseLike<T>) => void;
|
||
|
|
reject: (err: any) => void;
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Example Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// In parent component
|
||
|
|
const emit = defineEmits<{
|
||
|
|
(e: 'save', handler: AsyncHandler<boolean>, data: UserData): void;
|
||
|
|
(e: 'delete', handler: AsyncHandler<boolean>, id: string): void;
|
||
|
|
}>();
|
||
|
|
|
||
|
|
// In child component or hook
|
||
|
|
const emitsAsync = useAsyncEmits(emit);
|
||
|
|
|
||
|
|
const saveResult = await emitsAsync('save', userData);
|
||
|
|
const deleteResult = await emitsAsync('delete', userId);
|
||
|
|
```
|
||
|
|
|
||
|
|
### handleAsync
|
||
|
|
|
||
|
|
Wraps an async function to work with `AsyncHandler`.
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export function handleAsync<T, Args extends any[]>(handler: (...args: Args) => Promise<T>) {
|
||
|
|
return ({ resolve, reject }: AsyncHandler<T>, ...args: Args) => handler(...args).then(resolve, reject);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Example Usage
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const handleSave = handleAsync(async (data: UserData) => {
|
||
|
|
const response = await api.saveUser(data);
|
||
|
|
return response.ok;
|
||
|
|
});
|
||
|
|
|
||
|
|
emit('save', handleSave, userData);
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Object Utilities
|
||
|
|
|
||
|
|
**File**: `/home/hechang27/Documents/sprt/noob-components/plugs/util/objectUtil.ts`
|
||
|
|
|
||
|
|
### deepCopy
|
||
|
|
|
||
|
|
Creates a deep clone of an object using lodash.
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { cloneDeep } from "lodash-es";
|
||
|
|
|
||
|
|
export function deepCopy<T = any>(obj: T): T {
|
||
|
|
return cloneDeep(obj);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Note**: Uses `lodash-es` for tree-shaking support.
|
||
|
|
|
||
|
|
### clearObject
|
||
|
|
|
||
|
|
Removes all properties from an object.
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export function clearObject(obj: Record<string, any>) {
|
||
|
|
for (const key in obj) {
|
||
|
|
delete obj[key];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### clearAndAssign
|
||
|
|
|
||
|
|
Clears target object and assigns all properties from source.
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export function clearAndAssign(target: Record<string, any>, source: Record<string, any>) {
|
||
|
|
clearObject(target);
|
||
|
|
Object.assign(target, source);
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### unnest
|
||
|
|
|
||
|
|
Flattens a nested object property with a prefix.
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export function unnest(obj: Record<string, any>, key: string, prefix: string) {
|
||
|
|
const { [key]: toFlatten, ...rest } = obj;
|
||
|
|
const prefixed = Object.fromEntries(Object.entries(toFlatten).map(([k, v]) => [prefix.concat(k), v]));
|
||
|
|
return { ...rest, ...prefixed };
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Example
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const obj = { name: 'John', metadata: { age: 30, city: 'NYC' } };
|
||
|
|
const result = unnest(obj, 'metadata', 'metadata.');
|
||
|
|
// result: { name: 'John', 'metadata.age': 30, 'metadata.city': 'NYC' }
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Exports
|
||
|
|
|
||
|
|
**File**: `/home/hechang27/Documents/sprt/noob-components/plugs/util/index.ts`
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
export * from "./asyncUtil";
|
||
|
|
export * from "./objectUtil";
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Anti-Patterns
|
||
|
|
|
||
|
|
1. **Do not use `clearObject` on objects with prototypes** - This only works on plain objects
|
||
|
|
2. **Do not use deepCopy on objects with circular references** - It will throw an error
|
||
|
|
3. **Do not forget to import from `lodash-es`** - The main `lodash` package does not support tree-shaking
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
**Language**: English
|