《手写mini React》 调度流程 简单demo

63 阅读1分钟
// 任务队列,存储需要执行的任务
const taskQueue = {
  high: [],
  normal: [],
  low: []
};

// 标记是否有任务在执行中
let isPerformingTask = false;

// 创建 MessageChannel
const channel = new MessageChannel();
const { port1, port2 } = channel;

// 在 port1 上监听消息,用于执行任务
port1.onmessage = () => {
  performTask();
};


// 调度任务执行
function performTask() {
  for (let priority of ['high', 'normal', 'low']) {
    if (taskQueue[priority].length > 0) {
      isPerformingTask = true;
      const task = taskQueue[priority].shift();
      task();
      isPerformingTask = false;
      performTask(); // 继续执行下一个任务
      return;
    }
  }
}

// 添加任务到队列,并触发调度执行
function scheduleTask(task, priority = 'normal') {
  taskQueue[priority].push(task);

  // 如果没有任务在执行中,则开始执行任务
  if (!isPerformingTask) {
    port2.postMessage(null);
  }
}

// Fiber 数据结构
class FiberNode {
  constructor(instance, lane) {
    this.instance = instance; // React 组件实例
    this.props = instance.props;
    this.child = null; // 子节点
    this.sibling = null; // 兄弟节点
    this.return = null; // 父节点
    this.effectTag = null; // 更新类型标记
    this.lane = lane; // 优先级
  }
}

// 根 Fiber 节点
let currentRootFiber = null;

// Lane 模型
const Lanes = {
  HIGH: 1,
  NORMAL: 2,
  LOW: 3
};

// 创建 React 组件类
class Component {
  constructor(props) {
    this.props = props;
    this.state = {};
    this._fiber = null;
  }

  setState(newState) {
    this.state = Object.assign({}, this.state, newState);
    // 调度组件更新
    scheduleTask(() => {
      this._fiber = {
        ...this._fiber,
        effectTag: 'UPDATE'
      };
    }, Lanes.NORMAL);
  }

  render() {}
}

// 渲染函数
function render(element, container) {
  const fiber = new FiberNode({
    type: element.type,
    props: element.props
  }, Lanes.NORMAL);
  currentRootFiber = fiber;
  scheduleTask(() => {
    performWork(fiber);
  }, Lanes.HIGH);
}

// 执行组件更新
function performWork(fiber) {
  if (!fiber.instance) {
    return;
  }

  const children = fiber.instance.render();
  reconcileChildren(fiber, children);
}

// 协调子节点
function reconcileChildren(parentFiber, children) {
  let prevSibling = null;
  let oldFiber = parentFiber.child;

  for (let i = 0; i < children.length; i++) {
    const child = children[i];
    let newFiber = null;

    // TODO: 比较 oldFiber 和 child,生成 newFiber

    if (oldFiber) {
      // 更新
    } else {
      // 创建
    }

    if (i === 0) {
      parentFiber.child = newFiber;
    } else {
      prevSibling.sibling = newFiber;
    }

    prevSibling = newFiber;
    oldFiber = oldFiber ? oldFiber.sibling : null;
  }
}

// 示例使用
const rootElement = {
  type: 'div',
  props: {},
  children: [
    {type: 'p', props: {}, children: ['Hello, World!']}
  ]
};

// 渲染根组件
render(rootElement, document.getElementById('root'));