apiInject.ts 1.6 KB

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