renderEffect.ts 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import { ReactiveEffect, getCurrentScope } from '@vue/reactivity'
  2. import {
  3. type SchedulerJob,
  4. currentInstance,
  5. queueJob,
  6. queuePostFlushCb,
  7. simpleSetCurrentInstance,
  8. startMeasure,
  9. warn,
  10. } from '@vue/runtime-dom'
  11. import { type VaporComponentInstance, isVaporComponent } from './component'
  12. import { invokeArrayFns } from '@vue/shared'
  13. export function renderEffect(
  14. fn: () => void,
  15. noLifecycle = false,
  16. ): ReactiveEffect<void> {
  17. const instance = currentInstance as VaporComponentInstance | null
  18. const scope = getCurrentScope()
  19. if (__DEV__ && !__TEST__ && !scope && !isVaporComponent(instance)) {
  20. warn('renderEffect called without active EffectScope or Vapor instance.')
  21. }
  22. // renderEffect is always called after user has registered all hooks
  23. const hasUpdateHooks = instance && (instance.bu || instance.u)
  24. const renderEffectFn = noLifecycle
  25. ? fn
  26. : () => {
  27. if (__DEV__ && instance) {
  28. startMeasure(instance, `renderEffect`)
  29. }
  30. const prev = currentInstance
  31. simpleSetCurrentInstance(instance)
  32. if (scope) scope.on()
  33. if (hasUpdateHooks && instance.isMounted && !instance.isUpdating) {
  34. instance.isUpdating = true
  35. instance.bu && invokeArrayFns(instance.bu)
  36. fn()
  37. queuePostFlushCb(() => {
  38. instance.isUpdating = false
  39. instance.u && invokeArrayFns(instance.u)
  40. })
  41. } else {
  42. fn()
  43. }
  44. if (scope) scope.off()
  45. simpleSetCurrentInstance(prev, instance)
  46. if (__DEV__ && instance) {
  47. startMeasure(instance, `renderEffect`)
  48. }
  49. }
  50. const effect = new ReactiveEffect(renderEffectFn)
  51. const job: SchedulerJob = () => effect.dirty && effect.run()
  52. if (instance) {
  53. if (__DEV__) {
  54. effect.onTrack = instance.rtc
  55. ? e => invokeArrayFns(instance.rtc!, e)
  56. : void 0
  57. effect.onTrigger = instance.rtg
  58. ? e => invokeArrayFns(instance.rtg!, e)
  59. : void 0
  60. }
  61. job.i = instance
  62. job.id = instance.uid
  63. }
  64. effect.scheduler = () => queueJob(job)
  65. effect.run()
  66. return effect
  67. // TODO recurse handling
  68. }