1、前言
我们先来编写一个函数组件:
// src/indeximport React from '../react'function App(props){return <h1>H1,{props.name}!</h1>}const element = (<App name='foo'></App>)React.render(element, document.getElementById("root"))
函数组件的和标签组件有乱两个不同点:
- 函数组件中的fiber没有DOM节点
- children是通过运行函数得到的而不是props
2、功能实现
2.1 performUnitOfWork添加判断函数组件;
function performUnitOfWork(fiber) {// 判断是否为函数const isFunctionComponent =fiber.type instanceof Functionif (isFunctionComponent) {updateFunctionComponent(fiber)} else {// 更新普通节点updateHostComponent(fiber)}// 省略}function updateFunctionComponent(fiber) {// TODO}function updateHostComponent(fiber) {// TODO}
2.2 抽离performUnitOfWork中的reconcileChildren方法到updateHostComponent函数;
function updateHostComponent(fiber) {if (!fiber.dom) {fiber.dom = createDom(fiber)}reconcileChildren(fiber, fiber.props.children)}
2.3 处理函数组件,执行函数组件来获取children;
/*** 函数组件处理* @param {*} fiber*/function updateFunctionComponent(fiber) {const children = [fiber.type(fiber.props)]reconcileChildren(fiber, children)}
2.4 接下来我们处理一下没有DOM的fiber;
function commitWork (fiber) {// 省略let domParentFiber = fiber.parent// 一直向上找直到找到有dom的节点while (!domParentFiber.dom) {domParentFiber = domParentFiber.parent}const domParent = domParentFiber.dom// 省略}
2.5 当移除一个节点时,需要不断的向下找,直到找到一个具有 DOM 节点的子节点。
/*** 处理提交的fiber树* @param {*} fiber* @returns*/function commitWork(fiber) {// 省略// 处理删除节点标记} else if (fiber.effectTag === "DELETION") {commitDeletion(fiber, domParent)}// 省略}/*** 删除情况下,不断的向下找,直到找到有dom的子节点* @param {*} fiber* @param {*} domParent*/function commitDeletion(fiber, domParent) {if (fiber.dom) {domParent.removeChild(fiber.dom)} else {commitDeletion(fiber.child, domParent)}}
3、实现效果

