File tree Expand file tree Collapse file tree 4 files changed +107
-2
lines changed Expand file tree Collapse file tree 4 files changed +107
-2
lines changed Original file line number Diff line number Diff line change 110
110
111
111
- [x] 53-实现 monorepo
112
112
113
- - [ ] 54-实现 watchEffect
113
+ - [x ] 54-实现 watchEffect
114
114
115
115
### 课程地址
116
116
Original file line number Diff line number Diff line change
1
+ import { reactive } from "@guide-mini-vue/reactivity"
2
+ import { watchEffect } from "../src/apiWatch" ;
3
+ import { nextTick } from "../src/scheduler" ;
4
+ import { vi } from "vitest" ;
5
+
6
+
7
+ describe ( "api: watch" , ( ) => {
8
+ it ( "effect" , async ( ) => {
9
+ const state = reactive ( { count : 0 } ) ;
10
+ let dummy ;
11
+ watchEffect ( ( ) => {
12
+ dummy = state . count ;
13
+ } )
14
+ expect ( dummy ) . toBe ( 0 )
15
+
16
+ state . count ++
17
+ await nextTick ( ) ;
18
+ expect ( dummy ) . toBe ( 1 )
19
+ } )
20
+
21
+ it ( "stopping the watcher (effetc)" , async ( ) => {
22
+ const state = reactive ( { count : 0 } ) ;
23
+ let dummy ;
24
+ const stop : any = watchEffect ( ( ) => {
25
+ dummy = state . count ;
26
+ } )
27
+ expect ( dummy ) . toBe ( 0 )
28
+
29
+ stop ( )
30
+
31
+ state . count ++
32
+ await nextTick ( ) ;
33
+ // should not be update
34
+ expect ( dummy ) . toBe ( 0 )
35
+ } )
36
+
37
+ it ( "cleanup registration (effect)" , async ( ) => {
38
+ const state = reactive ( { count : 0 } ) ;
39
+ const cleanup = vi . fn ( ) ;
40
+ let dummy ;
41
+ const stop : any = watchEffect ( ( onCleanup ) => {
42
+ onCleanup ( cleanup )
43
+ dummy = state . count ;
44
+ } )
45
+ expect ( dummy ) . toBe ( 0 )
46
+
47
+ state . count ++
48
+ await nextTick ( ) ;
49
+ expect ( cleanup ) . toHaveBeenCalledTimes ( 1 ) ;
50
+ expect ( dummy ) . toBe ( 1 )
51
+
52
+ stop ( )
53
+ expect ( cleanup ) . toHaveBeenCalledTimes ( 2 ) ;
54
+ } )
55
+ } )
Original file line number Diff line number Diff line change
1
+ import { ReactiveEffect } from "../../reactivity/src/effect" ;
2
+ import { queueFlushCb } from "./scheduler" ;
3
+
4
+
5
+ export function watchEffect ( source ) {
6
+
7
+ function job ( ) {
8
+ effect . run ( )
9
+ }
10
+
11
+ let cleanup ;
12
+ const onCleanup = function ( fn ) {
13
+ cleanup = effect . onStop = ( ) => { [
14
+ fn ( )
15
+ ] }
16
+ }
17
+
18
+ function getter ( ) {
19
+ if ( cleanup ) {
20
+ cleanup ( ) ;
21
+ }
22
+ source ( onCleanup )
23
+ }
24
+
25
+ const effect = new ReactiveEffect ( getter , ( ) => {
26
+ queueFlushCb ( job )
27
+ } )
28
+
29
+ effect . run ( )
30
+
31
+ return ( ) => {
32
+ effect . stop ( )
33
+ }
34
+ }
Original file line number Diff line number Diff line change 1
1
2
2
const queue : any [ ] = [ ]
3
+ const activePreFlushCbs : any [ ] = [ ]
3
4
4
5
let isFlushPending = false
5
6
@@ -24,10 +25,25 @@ function queueFlush() {
24
25
nextTick ( flushJobs )
25
26
}
26
27
28
+ export function queueFlushCb ( job ) {
29
+ activePreFlushCbs . push ( job ) ;
30
+
31
+ queueFlush ( )
32
+ }
33
+
27
34
function flushJobs ( ) {
28
35
isFlushPending = false
36
+
37
+ flushPreFlushCbs ( )
38
+
29
39
let job ;
30
40
while ( ( job = queue . shift ( ) ) !== undefined ) {
31
41
job ( )
32
42
}
33
- }
43
+ }
44
+
45
+ function flushPreFlushCbs ( ) {
46
+ for ( let i = 0 ; i < activePreFlushCbs . length ; i ++ ) {
47
+ activePreFlushCbs [ i ] ( )
48
+ }
49
+ }
You can’t perform that action at this time.
0 commit comments