@@ -2,12 +2,14 @@ import { FiberNode, FiberRootNode, PendingPassiveEffects } from './fiber';
22import {
33 ChildDeletion ,
44 Flags ,
5+ LayoutMask ,
56 MutationMask ,
67 NoFlags ,
78 PassiveEffect ,
89 PassiveMask ,
910 Placement ,
10- Update
11+ Update ,
12+ Ref
1113} from './fiberFlags' ;
1214import { Effect , FCUpdateQueue } from './fiberHooks' ;
1315import { HookHasEffect } from './hookEffectTags' ;
@@ -29,42 +31,42 @@ import {
2931let nextEffect : FiberNode | null = null ;
3032
3133// 以DFS形式执行
32- export const commitMutationEffects = (
33- finishedWork : FiberNode ,
34- root : FiberRootNode
34+ const commitEffects = (
35+ phrase : 'mutation' | 'layout' ,
36+ mask : Flags ,
37+ callback : ( fiber : FiberNode , root : FiberRootNode ) => void
3538) => {
36- nextEffect = finishedWork ;
39+ return ( finishedWork : FiberNode , root : FiberRootNode ) => {
40+ nextEffect = finishedWork ;
3741
38- while ( nextEffect !== null ) {
39- // 向下遍历
40- const child : FiberNode | null = nextEffect . child ;
42+ while ( nextEffect !== null ) {
43+ // 向下遍历
44+ const child : FiberNode | null = nextEffect . child ;
4145
42- if (
43- ( nextEffect . subtreeFlags & ( MutationMask | PassiveMask ) ) !== NoFlags &&
44- child !== null
45- ) {
46- nextEffect = child ;
47- } else {
48- // 向上遍历
49- up: while ( nextEffect !== null ) {
50- commitMutationEffectsOnFiber ( nextEffect , root ) ;
51- const sibling : FiberNode | null = nextEffect . sibling ;
52-
53- if ( sibling !== null ) {
54- nextEffect = sibling ;
55- break up;
46+ if ( ( nextEffect . subtreeFlags & mask ) !== NoFlags && child !== null ) {
47+ nextEffect = child ;
48+ } else {
49+ // 向上遍历
50+ up: while ( nextEffect !== null ) {
51+ callback ( nextEffect , root ) ;
52+ const sibling : FiberNode | null = nextEffect . sibling ;
53+
54+ if ( sibling !== null ) {
55+ nextEffect = sibling ;
56+ break up;
57+ }
58+ nextEffect = nextEffect . return ;
5659 }
57- nextEffect = nextEffect . return ;
5860 }
5961 }
60- }
62+ } ;
6163} ;
6264
6365const commitMutationEffectsOnFiber = (
6466 finishedWork : FiberNode ,
6567 root : FiberRootNode
6668) => {
67- const flags = finishedWork . flags ;
69+ const { flags, tag } = finishedWork ;
6870
6971 if ( ( flags & Placement ) !== NoFlags ) {
7072 // 插入/移动
@@ -90,8 +92,59 @@ const commitMutationEffectsOnFiber = (
9092 commitPassiveEffect ( finishedWork , root , 'update' ) ;
9193 finishedWork . flags &= ~ PassiveEffect ;
9294 }
95+ if ( ( flags & Ref ) !== NoFlags && tag === HostComponent ) {
96+ safelyDetachRef ( finishedWork ) ;
97+ }
9398} ;
9499
100+ function safelyDetachRef ( current : FiberNode ) {
101+ const ref = current . ref ;
102+ if ( ref !== null ) {
103+ if ( typeof ref === 'function' ) {
104+ ref ( null ) ;
105+ } else {
106+ ref . current = null ;
107+ }
108+ }
109+ }
110+
111+ const commitLayoutEffectsOnFiber = (
112+ finishedWork : FiberNode ,
113+ root : FiberRootNode
114+ ) => {
115+ const { flags, tag } = finishedWork ;
116+
117+ if ( ( flags & Ref ) !== NoFlags && tag === HostComponent ) {
118+ // 绑定新的ref
119+ safelyAttachRef ( finishedWork ) ;
120+ finishedWork . flags &= ~ Ref ;
121+ }
122+ } ;
123+
124+ function safelyAttachRef ( fiber : FiberNode ) {
125+ const ref = fiber . ref ;
126+ if ( ref !== null ) {
127+ const instance = fiber . stateNode ;
128+ if ( typeof ref === 'function' ) {
129+ ref ( instance ) ;
130+ } else {
131+ ref . current = instance ;
132+ }
133+ }
134+ }
135+
136+ export const commitMutationEffects = commitEffects (
137+ 'mutation' ,
138+ MutationMask | PassiveMask ,
139+ commitMutationEffectsOnFiber
140+ ) ;
141+
142+ export const commitLayoutEffects = commitEffects (
143+ 'layout' ,
144+ LayoutMask ,
145+ commitLayoutEffectsOnFiber
146+ ) ;
147+
95148/**
96149 * 难点在于目标fiber的hostSibling可能并不是他的同级sibling
97150 * 比如: <A/><B/> 其中:function B() {return <div/>} 所以A的hostSibling实际是B的child
@@ -249,6 +302,7 @@ function commitDeletion(childToDelete: FiberNode, root: FiberRootNode) {
249302 case HostComponent :
250303 recordHostChildrenToDelete ( hostChildrenToDelete , unmountFiber ) ;
251304 // 解绑ref
305+ safelyDetachRef ( unmountFiber ) ;
252306 return ;
253307 case HostText :
254308 recordHostChildrenToDelete ( hostChildrenToDelete , unmountFiber ) ;
0 commit comments