useAttrs.ts 1.3 KB
Newer Older
V
vben 已提交
1
import { type Recordable } from '@vben/types';
V
vben 已提交
2
import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue';
V
vben 已提交
3

V
vben 已提交
4
interface Options {
V
vben 已提交
5 6
  excludeListeners?: boolean;
  excludeKeys?: string[];
7
  excludeDefaultKeys?: boolean;
V
vben 已提交
8 9 10 11 12
}

const DEFAULT_EXCLUDE_KEYS = ['class', 'style'];
const LISTENER_PREFIX = /^on[A-Z]/;

V
vben 已提交
13
function entries<T>(obj: Recordable<T>): [string, T][] {
V
vben 已提交
14 15 16
  return Object.keys(obj).map((key: string) => [key, obj[key]]);
}

V
vben 已提交
17
function useAttrs(options: Options = {}): Recordable<any> {
V
vben 已提交
18 19 20
  const instance = getCurrentInstance();
  if (!instance) return {};

V
vben 已提交
21
  const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = options;
V
vben 已提交
22
  const attrs = shallowRef({});
23
  const allExcludeKeys = excludeKeys.concat(excludeDefaultKeys ? DEFAULT_EXCLUDE_KEYS : []);
V
vben 已提交
24 25 26 27 28 29 30 31 32 33 34

  // Since attrs are not reactive, make it reactive instead of doing in `onUpdated` hook for better performance
  instance.attrs = reactive(instance.attrs);

  watchEffect(() => {
    const res = entries(instance.attrs).reduce((acm, [key, val]) => {
      if (!allExcludeKeys.includes(key) && !(excludeListeners && LISTENER_PREFIX.test(key))) {
        acm[key] = val;
      }

      return acm;
V
vben 已提交
35
    }, {} as Recordable<any>);
V
vben 已提交
36 37 38 39 40 41

    attrs.value = res;
  });

  return attrs;
}
V
vben 已提交
42 43

export { useAttrs };