刘光辉
9 小时以前 0dfe84494048ce27ba8449831782128412d3eb13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import type { ComputedRef, Ref } from 'vue';
 
import { computed, getCurrentInstance, unref, useAttrs, useSlots } from 'vue';
 
import { getFirstNonNullOrUndefined, kebabToCamelCase } from '@vben-core/shared/utils';
 
/**
 * 依次从插槽、attrs、props、state 中获取值
 * @param key
 * @param props
 * @param state
 */
export function usePriorityValue<T extends Record<string, any>, S extends Record<string, any>, K extends keyof T = keyof T>(
  key: K,
  props: T,
  state: Readonly<Ref<NoInfer<S>>> | undefined,
) {
  const instance = getCurrentInstance();
  const slots = useSlots();
  const attrs = useAttrs() as T;
 
  const value = computed((): T[K] => {
    // props不管有没有传,都会有默认值,会影响这里的顺序,
    // 通过判断原始props是否有值来判断是否传入
    const rawProps = (instance?.vnode?.props || {}) as T;
 
    const standardRawProps = {} as T;
 
    for (const [key, value] of Object.entries(rawProps)) {
      standardRawProps[kebabToCamelCase(key) as K] = value;
    }
    const propsKey = standardRawProps?.[key] === undefined ? undefined : props[key];
 
    // slot可以关闭
    return getFirstNonNullOrUndefined(slots[key as string], attrs[key], propsKey, state?.value?.[key as keyof S]) as T[K];
  });
 
  return value;
}
 
/**
 * 批量获取state中的值(每个值都是ref)
 * @param props
 * @param state
 */
export function usePriorityValues<T extends Record<string, any>, S extends Ref<Record<string, any>> = Readonly<Ref<NoInfer<T>, NoInfer<T>>>>(
  props: T,
  state: S | undefined,
) {
  const result: { [K in keyof T]: ComputedRef<T[K]> } = {} as never;
 
  (Object.keys(props) as (keyof T)[]).forEach((key) => {
    result[key] = usePriorityValue(key as keyof typeof props, props, state);
  });
 
  return result;
}
 
/**
 * 批量获取state中的值(集中在一个computed,用于透传)
 * @param props
 * @param state
 */
export function useForwardPriorityValues<T extends Record<string, any>, S extends Ref<Record<string, any>> = Readonly<Ref<NoInfer<T>, NoInfer<T>>>>(
  props: T,
  state: S | undefined,
) {
  const computedResult: { [K in keyof T]: ComputedRef<T[K]> } = {} as never;
 
  (Object.keys(props) as (keyof T)[]).forEach((key) => {
    computedResult[key] = usePriorityValue(key as keyof typeof props, props, state);
  });
 
  return computed(() => {
    const unwrapResult: Record<string, any> = {};
    Object.keys(props).forEach((key) => {
      unwrapResult[key] = unref(computedResult[key]);
    });
    return unwrapResult as { [K in keyof T]: T[K] };
  });
}