实现 React 类组件渲染

基于文章 实现 React Fragment 节点渲染

本文将介绍如何渲染类组件。

类组件已不推荐使用,本文不会讲太多。

js 复制代码
class ClassComponent extends Component {
    render() {
        return (
            <div>
                <h3>ClassComponent</h3>
            </div>
        )
    }
}

初始化 Component

js 复制代码
export function Component(props: any) {
    this.props = props;
}

// 区分类组件和函数组件
Component.prototype.isReactComponent = {}

Render 阶段

BeginWork 阶段

beginWork 函数增加类组件的 case。

js 复制代码
function updateClassComponent(current: Fiber | null, workInProgress: Fiber) {
  const { type, pendingProps } = workInProgress;
  const instance = new type(pendingProps);
  const children = instance.render();
  reconcileChildren(current, workInProgress, children);
  return workInProgress.child;
}

// 1. 处理当前 fiber,因为不同组件对应的 fiber 处理方式不同,
// 2. 返回子节点 child
export function beginWork(
  current: Fiber | null,
  workInProgress: Fiber
): Fiber | null {
  switch (workInProgress.tag) {
    // 根节点
    case HostRoot:
      return updateHostRoot(current, workInProgress);
    // 原生标签,div、span...
    case HostComponent:
      return updateHostComponent(current, workInProgress);
    // 文本节点
    case HostText:
      return updateHostText(current, workInProgress);
    // Fragment
    case Fragment:
      return updateHostFragment(current, workInProgress);
    case ClassComponent:
      return updateClassComponent(current, workInProgress);
  }
  throw new Error(
    `Unknown unit of work tag (${workInProgress.tag}). This error is likely caused by a bug in ` +
      "React. Please file an issue."
  );
}

createFiberFromTypeAndProps 函数,增加类组件的 case。

js 复制代码
// 根据 TypeAndProps 创建fiber
export function createFiberFromTypeAndProps(
  type: any,
  key: null | string,
  pendingProps: any
) {
  let fiberTag: WorkTag = IndeterminateComponent;

  if (isFn(type)) {
    // 函数组件
    if (type.prototype.isReactComponent) {
      fiberTag = ClassComponent;
    }
  } else if (isStr(type)) {
    // 原生标签
    fiberTag = HostComponent;
  } else if (type === REACT_FRAGMENT_TYPE) {
    fiberTag = Fragment;
  }
  const fiber = createFiber(fiberTag, pendingProps, key);
  fiber.elementType = type;
  fiber.type = type;
  return fiber;
}

Complete 阶段

completeWork 函数增加类组件的 case。

js 复制代码
function completeWork(
  current: Fiber | null,
  workInProgress: Fiber
): Fiber | null {
  const newProps = workInProgress.pendingProps;
  switch (workInProgress.tag) {
    case Fragment:
    case HostRoot:
    case ClassComponent:{
      return null;
    }
    case HostComponent: {
      // 原生标签,type 是标签名
      const { type } = workInProgress;
        // 1. 创建真实 DOM
        const instance = document.createElement(type);
        // 2. 初始化 DOM 属性
        finalizeInitialChildren(instance, newProps);
        // 3. 把子 dom 挂载到父 dom 上
        appendAllChildren(instance, workInProgress);
        workInProgress.stateNode = instance;
      return null;
    }
    case HostText: {
      workInProgress.stateNode = document.createTextNode(newProps);
      return null;
    }
  }

  throw new Error(
    `Unknown unit of work tag (${workInProgress.tag}). This error is likely caused by a bug in ` +
      "React. Please file an issue."
  );
}
相关推荐
清灵xmf12 分钟前
CSS field-sizing 让表单「活」起来
前端·css·field-sizing
文火冰糖的硅基工坊27 分钟前
[光学原理与应用-480]:《国产检测设备对比表》
前端·人工智能·系统架构·制造·半导体·产业链
excel35 分钟前
Qiankun 子应用生命周期及使用场景解析
前端
weixin_4462608539 分钟前
Django - 让开发变得简单高效的Web框架
前端·数据库·django
ObjectX前端实验室2 小时前
【react18原理探究实践】异步可中断 & 时间分片
前端·react.js
SoaringHeart2 小时前
Flutter进阶:自定义一个 json 转 model 工具
前端·flutter·dart
努力打怪升级2 小时前
Rocky Linux 8 远程管理配置指南(宿主机 VNC + KVM 虚拟机 VNC)
前端·chrome
brzhang2 小时前
AI Agent 干不好活,不是它笨,告诉你一个残忍的现实,是你给他的工具太难用了
前端·后端·架构
brzhang2 小时前
一文说明白为什么现在 AI Agent 都把重点放在上下文工程(context engineering)上?
前端·后端·架构
reembarkation2 小时前
自定义分页控件,只显示当前页码的前后N页
开发语言·前端·javascript