apiInject.ts 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import { currentInstance } from './component'
  2. import { currentRenderingInstance } from './componentRenderUtils'
  3. import { warn } from './warning'
  4. export interface InjectionKey<T> extends Symbol {}
  5. export function provide<T>(key: InjectionKey<T> | string, value: T) {
  6. if (!currentInstance) {
  7. if (__DEV__) {
  8. warn(`provide() can only be used inside setup().`)
  9. }
  10. } else {
  11. let provides = currentInstance.provides
  12. // by default an instance inherits its parent's provides object
  13. // but when it needs to provide values of its own, it creates its
  14. // own provides object using parent provides object as prototype.
  15. // this way in `inject` we can simply look up injections from direct
  16. // parent and let the prototype chain do the work.
  17. const parentProvides =
  18. currentInstance.parent && currentInstance.parent.provides
  19. if (parentProvides === provides) {
  20. provides = currentInstance.provides = Object.create(parentProvides)
  21. }
  22. // TS doesn't allow symbol as index type
  23. provides[key as string] = value
  24. }
  25. }
  26. export function inject<T>(key: InjectionKey<T> | string): T | undefined
  27. export function inject<T>(key: InjectionKey<T> | string, defaultValue: T): T
  28. export function inject(
  29. key: InjectionKey<any> | string,
  30. defaultValue?: unknown
  31. ) {
  32. // fallback to `currentRenderingInstance` so that this can be called in
  33. // a functional component
  34. const instance = currentInstance || currentRenderingInstance
  35. if (instance) {
  36. const provides = instance.provides
  37. if (key in provides) {
  38. // TS doesn't allow symbol as index type
  39. return provides[key as string]
  40. } else if (defaultValue !== undefined) {
  41. return defaultValue
  42. } else if (__DEV__) {
  43. warn(`injection "${String(key)}" not found.`)
  44. }
  45. } else if (__DEV__) {
  46. warn(`inject() can only be used inside setup() or functional components.`)
  47. }
  48. }