useRouteMeta.ts 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. import { tryOnScopeDispose } from '@vueuse/core';
  2. import type { MaybeRefOrGetter, Ref } from 'vue';
  3. import type { RouteMeta } from 'vue-router';
  4. export interface ReactiveRouteOptionsWithTransform<V, R> {
  5. route?: ReturnType<typeof useRoute>;
  6. transform?: (val: V) => R;
  7. }
  8. export function useRouteMeta<T extends RouteMeta = RouteMeta, K = T>(
  9. name: keyof T,
  10. defaultValue?: MaybeRefOrGetter,
  11. options: ReactiveRouteOptionsWithTransform<T, K> = {},
  12. ): Ref<K> {
  13. const {
  14. route = useRoute(),
  15. transform = value => value as any as K,
  16. } = options;
  17. let meta = route.meta[ name ] as any;
  18. tryOnScopeDispose(() => { meta = undefined; });
  19. let _trigger: () => void;
  20. const proxy = customRef<any>((track, trigger) => {
  21. _trigger = trigger;
  22. return {
  23. get() {
  24. track();
  25. return transform(meta !== undefined && meta !== '' ? meta : toValue(defaultValue));
  26. },
  27. set(v) {
  28. meta = v;
  29. trigger();
  30. },
  31. };
  32. });
  33. watch(
  34. () => route.meta[ name ],
  35. (v) => {
  36. if ( meta === v ) return;
  37. meta = v;
  38. _trigger();
  39. },
  40. { flush: 'sync' },
  41. );
  42. return proxy as Ref<K>;
  43. }