UNPKG

hm-react-cli

Version:

Create a Huimei React project by module

266 lines (257 loc) 8.62 kB
import { emptyObject, returnFalse } from 'react-core/util'; import { NOWORK, WORKING, PLACE, CONTENT, DUPLEX, ATTR, //UPDATE DETACH, //DELETION HOOK, REF, CALLBACK, PASSIVE, CAPTURE, effectLength, effectNames } from './effectTag'; import { guardCallback, removeFormBoundaries } from './ErrorBoundary'; import { fakeObject } from 'react-core/Component'; import { Renderer } from 'react-core/createRenderer'; import { Refs } from './Refs'; /** * COMMIT阶段也做成深度调先遍历 * @param {*} fiber * @param {*} topFiber */ var domFns = ['insertElement', 'updateContent', 'updateAttribute']; var domEffects = [PLACE, CONTENT, ATTR]; var domRemoved = []; var passiveFibers = []; function commitDFSImpl(fiber) { let topFiber = fiber; outerLoop: while (true) { //逐步向下执行所有移除与插入操作 if (fiber.effects && fiber.effects.length) { //fiber里面是被重用的旧节点与无法重用的旧节点 fiber.effects.forEach(disposeFiber); delete fiber.effects; } if (fiber.effectTag % PLACE == 0) { // DOM节点插入或移除 domEffects.forEach(function (effect, i) { if (fiber.effectTag % effect == 0) { Renderer[domFns[i]](fiber); fiber.effectTag /= effect; } }); fiber.hasMounted = true; } else { // 边界组件的清洗工件 if (fiber.catchError) { removeFormBoundaries(fiber); disposeFibers(fiber); } } if (fiber.updateFail) { delete fiber.updateFail; } if (fiber.child && fiber.child.effectTag > NOWORK) { fiber = fiber.child; continue; } let f = fiber; while (f) { if (f.effectTag === WORKING) { f.effectTag = NOWORK; f.hasMounted = true;//做react hooks新时新加的 } else if (f.effectTag > WORKING) { commitEffects(f); f.hasMounted = true; if (f.capturedValues) { f.effectTag = CAPTURE; } } if (f === topFiber || f.hostRoot) { break outerLoop; } if (f.sibling) { fiber = f.sibling; continue outerLoop; } f = f.return; } } } export function commitDFS(effects) { Renderer.batchedUpdates(function () { var el; while ((el = effects.shift())) { //处理retry组件 if (el.effectTag === DETACH && el.caughtError) { disposeFiber(el); } else { commitDFSImpl(el); } if (passiveFibers.length) { passiveFibers.forEach(function (fiber) { safeInvokeHooks(fiber.updateQueue, 'passive', 'unpassive'); }); passiveFibers.length = 0; } if (domRemoved.length) { domRemoved.forEach(Renderer.removeElement); domRemoved.length = 0; } } }, {}); let error = Renderer.catchError; if (error) { delete Renderer.catchError; throw error; } } /** * 执行其他任务 * * @param {Fiber} fiber */ export function commitEffects(fiber) { let instance = fiber.stateNode || emptyObject; let amount = fiber.effectTag; let updater = instance.updater || fakeObject; for (let i = 0; i < effectLength; i++) { let effectNo = effectNames[i]; if (effectNo > amount) { break; } if (amount % effectNo === 0) { amount /= effectNo; //如果能整除 switch (effectNo) { case WORKING: break; case DUPLEX: Renderer.updateControlled(fiber); break; case HOOK: if (instance.__isStateless) { safeInvokeHooks(fiber.updateQueue, 'layout', 'unlayout'); } else if (fiber.hasMounted) { guardCallback(instance, 'componentDidUpdate', [ updater.prevProps, updater.prevState, updater.snapshot ]); } else { fiber.hasMounted = true; guardCallback(instance, 'componentDidMount', []); } delete fiber._hydrating; //这里发现错误,说明它的下方组件出现错误,不能延迟到下一个生命周期 if (fiber.catchError) { fiber.effectTag = amount; return; } break; case PASSIVE: passiveFibers.push(fiber); break; case REF: Refs.fireRef(fiber, instance); break; case CALLBACK: //ReactDOM.render/forceUpdate/setState callback var queue = fiber.pendingCbs; fiber._hydrating = true; //setState回调里再执行setState queue.forEach(function (fn) { fn.call(instance); }); delete fiber._hydrating; delete fiber.pendingCbs; break; case CAPTURE: // 23 // console.log("进入CAPTURE"); var values = fiber.capturedValues; fiber.caughtError = true; var a = values.shift(); var b = values.shift(); if (!values.length) { fiber.effectTag = amount; delete fiber.capturedValues; } instance.componentDidCatch(a, b); break; } } } fiber.effectTag = NOWORK; } export function disposeFibers(fiber) { let list = [fiber.oldChildren, fiber.children]; for (let i = 0; i < 2; i++) { let c = list[i]; if (c) { for (let i in c) { let child = c[i]; if (!child.disposed && child.hasMounted) { disposeFiber(child, true); disposeFibers(child); } } } } delete fiber.child; delete fiber.lastChild; delete fiber.oldChildren; fiber.children = {}; } function safeInvokeHooks(upateQueue, create, destory, isUnmount) { const prevDestroyList = upateQueue[destory]; const curCreateList = upateQueue[create]; curCreateList && curCreateList.forEach((createFn, i) => { const depsChange = typeof createFn === 'function'; if (depsChange || isUnmount) { const prevDestroyFn = prevDestroyList[i]; if (typeof prevDestroyFn === 'function') { prevDestroyFn(); } } }); !isUnmount && curCreateList && curCreateList.forEach((createFn, i) => { if (typeof createFn === 'function') { const destroyFn = createFn(); prevDestroyList[i] = destroyFn; } }) } function disposeFiber(fiber, force) { let { stateNode, effectTag } = fiber; if (!stateNode) { return; } let isStateless = stateNode.__isStateless; if (!isStateless && fiber.ref) { Refs.fireRef(fiber, null); } if (effectTag % DETACH == 0 || force === true) { if (fiber.tag > 3) { domRemoved.push(fiber); } else { Renderer.onDispose(fiber); if (fiber.hasMounted) { if (isStateless) { safeInvokeHooks(fiber.updateQueue, 'layout', 'unlayout', true); safeInvokeHooks(fiber.updateQueue, 'passive', 'unpassive', true); } stateNode.updater.enqueueSetState = returnFalse; guardCallback(stateNode, 'componentWillUnmount', []); delete fiber.stateNode; } } delete fiber.alternate; delete fiber.hasMounted; fiber.disposed = true; } fiber.effectTag = NOWORK; }