use-priority-value.ts 2.6 KB

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