1
- import { ReactiveEffect , getCurrentScope } from '@vue/reactivity'
1
+ import {
2
+ type EffectScope ,
3
+ ReactiveEffect ,
4
+ getCurrentScope ,
5
+ } from '@vue/reactivity'
2
6
import {
3
7
type SchedulerJob ,
4
8
currentInstance ,
@@ -11,60 +15,94 @@ import {
11
15
import { type VaporComponentInstance , isVaporComponent } from './component'
12
16
import { invokeArrayFns } from '@vue/shared'
13
17
14
- export function renderEffect ( fn : ( ) => void , noLifecycle = false ) : void {
15
- const instance = currentInstance as VaporComponentInstance | null
16
- const scope = getCurrentScope ( )
17
- if ( __DEV__ && ! __TEST__ && ! scope && ! isVaporComponent ( instance ) ) {
18
- warn ( 'renderEffect called without active EffectScope or Vapor instance.' )
19
- }
18
+ class RenderEffect extends ReactiveEffect {
19
+ i : VaporComponentInstance | null
20
+ scope : EffectScope | undefined
21
+ baseJob : SchedulerJob
22
+ postJob : SchedulerJob
23
+
24
+ constructor ( public render : ( ) => void ) {
25
+ super ( )
26
+ const instance = currentInstance as VaporComponentInstance | null
27
+ const scope = getCurrentScope ( )
28
+ if ( __DEV__ && ! __TEST__ && ! scope && ! isVaporComponent ( instance ) ) {
29
+ warn ( 'renderEffect called without active EffectScope or Vapor instance.' )
30
+ }
31
+
32
+ this . baseJob = ( ) => {
33
+ if ( this . dirty ) {
34
+ this . run ( )
35
+ }
36
+ }
37
+ this . postJob = ( ) => {
38
+ instance ! . isUpdating = false
39
+ instance ! . u && invokeArrayFns ( instance ! . u )
40
+ }
20
41
21
- // renderEffect is always called after user has registered all hooks
22
- const hasUpdateHooks = instance && ( instance . bu || instance . u )
23
- const renderEffectFn = noLifecycle
24
- ? fn
25
- : ( ) => {
26
- if ( __DEV__ && instance ) {
27
- startMeasure ( instance , `renderEffect` )
28
- }
29
- const prev = currentInstance
30
- simpleSetCurrentInstance ( instance )
31
- if ( scope ) scope . on ( )
32
- if ( hasUpdateHooks && instance . isMounted && ! instance . isUpdating ) {
33
- instance . isUpdating = true
34
- instance . bu && invokeArrayFns ( instance . bu )
35
- fn ( )
36
- queuePostFlushCb ( ( ) => {
37
- instance . isUpdating = false
38
- instance . u && invokeArrayFns ( instance . u )
39
- } )
40
- } else {
41
- fn ( )
42
- }
43
- if ( scope ) scope . off ( )
44
- simpleSetCurrentInstance ( prev , instance )
45
- if ( __DEV__ && instance ) {
46
- startMeasure ( instance , `renderEffect` )
47
- }
42
+ if ( instance ) {
43
+ if ( __DEV__ ) {
44
+ this . onTrack = instance . rtc
45
+ ? e => invokeArrayFns ( instance . rtc ! , e )
46
+ : void 0
47
+ this . onTrigger = instance . rtg
48
+ ? e => invokeArrayFns ( instance . rtg ! , e )
49
+ : void 0
48
50
}
51
+ this . baseJob . i = instance
52
+ this . baseJob . id = instance . uid
53
+ }
54
+
55
+ this . i = instance
56
+ this . scope = scope
49
57
50
- const effect = new ReactiveEffect ( renderEffectFn )
51
- const job : SchedulerJob = ( ) => effect . dirty && effect . run ( )
58
+ // TODO recurse handling
59
+ }
52
60
53
- if ( instance ) {
54
- if ( __DEV__ ) {
55
- effect . onTrack = instance . rtc
56
- ? e => invokeArrayFns ( instance . rtc ! , e )
57
- : void 0
58
- effect . onTrigger = instance . rtg
59
- ? e => invokeArrayFns ( instance . rtg ! , e )
60
- : void 0
61
+ callback ( ) {
62
+ const instance = this . i !
63
+ const scope = this . scope
64
+ // renderEffect is always called after user has registered all hooks
65
+ const hasUpdateHooks = instance && ( instance . bu || instance . u )
66
+ if ( __DEV__ && instance ) {
67
+ startMeasure ( instance , `renderEffect` )
61
68
}
62
- job . i = instance
63
- job . id = instance . uid
69
+ const prev = currentInstance
70
+ simpleSetCurrentInstance ( instance )
71
+ if ( scope ) scope . on ( )
72
+ if ( hasUpdateHooks && instance . isMounted && ! instance . isUpdating ) {
73
+ instance . isUpdating = true
74
+ instance . bu && invokeArrayFns ( instance . bu )
75
+ this . render ( )
76
+ queuePostFlushCb ( this . postJob )
77
+ } else {
78
+ this . render ( )
79
+ }
80
+ if ( scope ) scope . off ( )
81
+ simpleSetCurrentInstance ( prev , instance )
82
+ if ( __DEV__ && instance ) {
83
+ startMeasure ( instance , `renderEffect` )
84
+ }
85
+ }
86
+
87
+ scheduler ( ) {
88
+ queueJob ( this . baseJob )
64
89
}
90
+ }
65
91
66
- effect . scheduler = ( ) => queueJob ( job )
67
- effect . run ( )
92
+ class RenderEffect_NoLifecycle extends RenderEffect {
93
+ constructor ( render : ( ) => void ) {
94
+ super ( render )
95
+ }
68
96
69
- // TODO recurse handling
97
+ callback ( ) {
98
+ this . render ( )
99
+ }
100
+ }
101
+
102
+ export function renderEffect ( fn : ( ) => void , noLifecycle = false ) : void {
103
+ if ( noLifecycle ) {
104
+ new RenderEffect_NoLifecycle ( fn ) . run ( )
105
+ } else {
106
+ new RenderEffect ( fn ) . run ( )
107
+ }
70
108
}
0 commit comments