We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fiber
ref
commit
commitAllHostEffects
dom
commitDetachRef
commitAllLifeCycles
commitAttachRef
ref 是函数
ref 函数
instance
// createRef function createRef(): RefObject { const refObject = { current: null, }; if (__DEV__) { Object.seal(refObject); } return refObject; }
ref 方法
class instanc
refs[stringRef]
this.refs.stringRef
// ReactChildFiber.js 调和子节点复用或者创建新的fiber 节点时处理 ref function coerceRef( returnFiber: Fiber, current: Fiber | null, element: ReactElement, ) { let mixedRef = element.ref; if ( mixedRef !== null && typeof mixedRef !== 'function' && typeof mixedRef !== 'object' ) { // 处理字符串 ref // createElement -> 传入 owner 为 ReactCurrentOwner.current ,而在 finishClassComponent 中设置 ReactCurrentOwner.current= workInProgress; // 之后子节点会在 instance.render 当中被创建,进入到调和子节点中 // _owner 即 fiber 对象 if (element._owner) { const owner: ?Fiber = (element._owner: any); let inst; if (owner) { const ownerFiber = ((owner: any): Fiber); // classComponent 的实例 inst = ownerFiber.stateNode; } const stringRef = '' + mixedRef; // Check if previous string ref matches new string ref if ( current !== null && current.ref !== null && typeof current.ref === 'function' && current.ref._stringRef === stringRef // _stringRef 如果没有变化,不需要重新生成 ref 方法 ) { return current.ref; } const ref = function(value) { // 即组件里使用的 this.refs let refs = inst.refs; if (refs === emptyRefsObject) { // This is a lazy pooled frozen object, so we need to initialize. refs = inst.refs = {}; } // dom 节点 或者 instance 被挂载的时候会调用 ref 这个方法,value 即传入它自己的实例 if (value === null) { delete refs[stringRef]; } else { // 设置到 this.refs 的 stringRef 属性上 refs[stringRef] = value; } }; ref._stringRef = stringRef; // 这个方法在 commit 阶段被调用 return ref; } else { // 。。。 } } return mixedRef; }
// dom 节点的插入、删除、更新 function commitAllHostEffects() { while (nextEffect !== null) { recordEffect(); const effectTag = nextEffect.effectTag; // 判断内部是否为文字节点 if (effectTag & ContentReset) { // 文字节点设置为空字符串 commitResetTextContent(nextEffect); } // ref操作 if (effectTag & Ref) { const current = nextEffect.alternate; // 非首次渲染 if (current !== null) { commitDetachRef(current); } } // ... } } // commitDetachRef function commitDetachRef(current: Fiber) { const currentRef = current.ref; if (currentRef !== null) { if (typeof currentRef === 'function') { // 如果是函数则传入 null 执行 currentRef(null); } else { // 其他类型直接赋值 null currentRef.current = null; } } }
function commitAttachRef(finishedWork: Fiber) { const ref = finishedWork.ref; if (ref !== null) { const instance = finishedWork.stateNode; let instanceToUse; // 获取 instance switch (finishedWork.tag) { case HostComponent: instanceToUse = getPublicInstance(instance); break; default: instanceToUse = instance; } if (typeof ref === 'function') { // 这里即函数式 ref 真正挂载 instance, 字符串 ref 创建的 ref 函数也在这执行,将 this.refs[stringRef] = instanceToUse ref(instanceToUse); } else { // 其他类型直接赋值 ref.current ref.current = instanceToUse; } } }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
ref
fiber
的时候(调和子节点里面)处理ref
commit
开始前,第二次循环执行commitAllHostEffects
(dom
的增、删、改)过程中,调用commitDetachRef
将ref
从之前挂载的地方卸载commitAllLifeCycles
调用commitAttachRef
将更新过后的节点挂载到ref
上,如果ref 是函数
则执行ref 函数
将fiber
的instance
作为参数传入coerceRef
ref
,需要创建一个ref 方法
,挂载在fiber
的ref
属性上,在这个方法里将更新过的dom
节点或者class instanc
e 挂载在实例的refs[stringRef]
上(即commitAttachRef
过程)this.refs.stringRef
获取ref
,即将被废弃commitDetachRef
commitAllHostEffects
先卸载原有的ref
commitAttachRef
commitAllLifeCycles
中将更新后的instance
挂载到ref
上The text was updated successfully, but these errors were encountered: