react渲染源码实现

19 阅读2分钟
const { createElement } = require("react");

const React = {
  // 组件状态存储 - 为每个组件实例单独存储
  states: new Map(),
  stateIndex: 0,
  
  // 副作用存储
  effects: new Map(),
  effectIndex: 0,
  
  // 清理函数存储
  cleanups: new Map(),
  
  // 更新队列
  updateQueue: new Set(),
  
  // 当前正在渲染的组件
  currentComponent: null,
  
  // 渲染调度器
  isRendering: false,
  pendingUpdate: false,
  
  // 创建虚拟DOM
  createElement(type, props, ...children) {
    return {
      type,
      props: {
        ...props,
        children: children.flat().filter(Boolean).map(child => 
          typeof child === 'object' ? child : String(child)
        ),
      },
    };
  },

  // 组件渲染管线
  render(component, container) {
    if (!container) {
      console.error('Container is required');
      return;
    }
    
    // 重置索引
    this.resetIndexes();
    
    // 设置当前组件并执行
    this.currentComponent = component;
    const vnode = typeof component === 'function' ? component() : component;
    this.currentComponent = null;
    
    // 创建真实DOM
    const dom = this.createDOM(vnode);
    
    // 清空容器并挂载
    if (container && container.nodeType === 1) {
      container.innerHTML = "";
      container.appendChild(dom);
    }
    
    // 执行effect
    this.runEffects(component);
    
    // 返回更新函数
    const update = () => {
      this.scheduleUpdate(component, container);
    };
    
    // 为组件实例存储更新函数
    if (!this.updaters) this.updaters = new Map();
    this.updaters.set(component, { update, container });
    
    return update;
  },

  // 调度更新
  scheduleUpdate(component, container) {
    if (this.isRendering) {
      this.pendingUpdate = true;
      return;
    }
    
    this.updateQueue.add(component);
    
    // 使用微任务进行批量更新
    Promise.resolve().then(() => {
      if (this.updateQueue.size > 0) {
        const components = Array.from(this.updateQueue);
        this.updateQueue.clear();
        
        components.forEach(comp => {
          const updater = this.updaters?.get(comp);
          if (updater) {
            this.performUpdate(comp, updater.container);
          }
        });
      }
    });
  },

  // 执行更新
  performUpdate(component, container) {
    this.isRendering = true;
    
    // 重置索引
    this.resetIndexes();
    
    // 设置当前组件
    this.currentComponent = component;
    const vnode = component();
    this.currentComponent = null;
    
    // 执行清理函数
    this.cleanupEffects(component);
    
    // 重新渲染
    const dom = this.createDOM(vnode);
    
    if (container && container.nodeType === 1) {
      const oldDom = container.firstChild;
      if (oldDom && oldDom.parentNode) {
        container.replaceChild(dom, oldDom);
      } else {
        container.innerHTML = "";
        container.appendChild(dom);
      }
    }
    
    // 执行effect
    this.runEffects(component);
    
    this.isRendering = false;
    
    if (this.pendingUpdate) {
      this.pendingUpdate = false;
      this.scheduleUpdate(component, container);
    }
  },

  // 重置所有索引
  resetIndexes() {
    this.stateIndex = 0;
    this.effectIndex = 0;
  },

  // 创建真实DOM
  createDOM(vnode) {
    // 处理文本节点
    if (typeof vnode === "string" || typeof vnode === "number") {
      return document.createTextNode(vnode);
    }
    
    // 处理null/undefined
    if (vnode == null || vnode === false) {
      return document.createTextNode('');
    }
    
    const { type, props } = vnode;
    
    // 处理函数组件
    if (typeof type === 'function') {
      return this.createDOM(type(props));
    }
    
    // 创建元素
    const dom = document.createElement(type);
    
    // 处理属性
    for (const key in props) {
      if (key === "children") continue;
      
      // 处理事件
      if (key.startsWith("on") && typeof props[key] === 'function') {
        const eventName = key.slice(2).toLowerCase();
        dom.addEventListener(eventName, props[key]);
      } else if (key === 'className') {
        // 处理className
        dom.setAttribute('class', props[key]);
      } else if (key === 'style' && typeof props[key] === 'object') {
        // 处理style对象
        Object.assign(dom.style, props[key]);
      } else {
        // 设置普通属性
        dom.setAttribute(key, props[key]);
      }
    }
    
    // 递归处理子节点
    if (props.children) {
      props.children.forEach((child) => {
        if (child != null) {
          dom.appendChild(this.createDOM(child));
        }
      });
    }
    
    return dom;
  },

  // 清理副作用
  cleanupEffects(component) {
    const componentEffects = this.effects.get(component) || [];
    const componentCleanups = this.cleanups.get(component) || [];
    
    // 执行清理函数
    componentCleanups.forEach(cleanup => {
      if (typeof cleanup === 'function') {
        try {
          cleanup();
        } catch (error) {
          console.error('Error in cleanup function:', error);
        }
      }
    });
    
    // 清空清理函数
    if (this.cleanups.has(component)) {
      this.cleanups.set(component, []);
    }
  },

  // 运行副作用
  runEffects(component) {
    const componentEffects = this.effects.get(component) || [];
    
    // 存储新的清理函数
    const newCleanups = [];
    
    // 执行effect
    componentEffects.forEach((effect, index) => {
      const { callback, dependencies } = effect;
      
      // 检查依赖是否变化
      let hasChanged = true;
      if (dependencies) {
        const prevEffect = componentEffects[index];
        if (prevEffect && prevEffect.prevDependencies) {
          hasChanged = dependencies.some((dep, i) => 
            !Object.is(dep, prevEffect.prevDependencies[i])
          );
        }
      }
      
      if (hasChanged) {
        // 执行effect
        const cleanup = callback();
        if (typeof cleanup === 'function') {
          newCleanups.push(cleanup);
        }
        
        // 更新依赖
        effect.prevDependencies = dependencies;
      }
    });
    
    // 保存清理函数
    this.cleanups.set(component, newCleanups);
  },
};

// useState实现
function useState(initialValue) {
  const component = React.currentComponent;
  if (!component) {
    throw new Error("useState must be called within a component");
  }
  
  // 获取当前组件的状态数组
  if (!React.states.has(component)) {
    React.states.set(component, []);
  }
  const componentStates = React.states.get(component);
  
  // 获取当前状态索引
  const currentIndex = React.stateIndex;
  
  // 初始化状态
  if (componentStates[currentIndex] === undefined) {
    componentStates[currentIndex] = 
      typeof initialValue === 'function' 
        ? initialValue() 
        : initialValue;
  }
  
  // 创建状态引用
  const state = componentStates[currentIndex];
  
  // 创建setState函数
  const setState = (newState) => {
    const currentValue = componentStates[currentIndex];
    
    if (typeof newState === 'function') {
      newState = newState(currentValue);
    }
    
    // 只有值变化时才更新
    if (!Object.is(currentValue, newState)) {
      componentStates[currentIndex] = newState;
      
      // 获取组件的更新器
      const updater = React.updaters?.get(component);
      if (updater) {
        React.scheduleUpdate(component, updater.container);
      }
    }
  };
  
  // 递增状态索引
  React.stateIndex++;
  
  return [state, setState];
}

// useEffect实现
function useEffect(callback, dependencies) {
  const component = React.currentComponent;
  if (!component) {
    throw new Error("useEffect must be called within a component");
  }
  
  // 初始化副作用存储
  if (!React.effects.has(component)) {
    React.effects.set(component, []);
  }
  const componentEffects = React.effects.get(component);
  
  // 获取当前索引
  const currentIndex = React.effectIndex;
  
  // 存储副作用
  componentEffects[currentIndex] = {
    callback,
    dependencies,
    prevDependencies: null,
  };
  
  // 递增副作用索引
  React.effectIndex++;
}


module.exports = { React, useState, useEffect};