迷你react和真正的源码有哪些区别呢

  • 在render阶段咱们遍历了整颗Fiber树,在源码中如果节点什么都没扭转会命中优化的逻辑,而后跳过这个节点的遍历
  • commit咱们也遍历了整颗Fiber树,源码中只遍历带有effect的Fiber节点,也就是遍历effectList
  • 每次遍历的时候咱们都是新建节点,源码中某些条件会复用节点
  • 没有用到优先级

第一步:渲染器和入口函数

const React = {  createElement,  render,};const container = document.getElementById("root");const updateValue = (e) => {  rerender(e.target.value);};const rerender = (value) => {  const element = (    <div>      <input onInput={updateValue} value={value} />      <h2>Hello {value}</h2>    </div>  );  React.render(element, container);};rerender("World");

第二步:创立dom节点函数

//创立elementfunction createElement(type, props, ...children) {  return {    type,    props: {      ...props,      children: children.map((child) => (typeof child === "object" ? child : createTextElement(child))),    },  };}//创立text类型function createTextElement(text) {  return {    type: "TEXT_ELEMENT",    props: {      nodeValue: text,      children: [],    },  };}//创立domfunction createDom(fiber) {  const dom = fiber.type === "TEXT_ELEMENT" ? document.createTextNode("") : document.createElement(fiber.type);  updateDom(dom, {}, fiber.props);  return dom;}

第三步:更新节点函数

const isEvent = (key) => key.startsWith("on");const isProperty = (key) => key !== "children" && !isEvent(key);const isNew = (prev, next) => (key) => prev[key] !== next[key];const isGone = (prev, next) => (key) => !(key in next);//更新节点属性function updateDom(dom, prevProps, nextProps) {  //删除老的事件  Object.keys(prevProps)    .filter(isEvent)    .filter((key) => !(key in nextProps) || isNew(prevProps, nextProps)(key))    .forEach((name) => {      const eventType = name.toLowerCase().substring(2);      dom.removeEventListener(eventType, prevProps[name]);    });  // 删除旧属性  Object.keys(prevProps)    .filter(isProperty)    .filter(isGone(prevProps, nextProps))    .forEach((name) => {      dom[name] = "";    });  // 设置新属性  Object.keys(nextProps)    .filter(isProperty)    .filter(isNew(prevProps, nextProps))    .forEach((name) => {      dom[name] = nextProps[name];    });  // 减少新事件  Object.keys(nextProps)    .filter(isEvent)    .filter(isNew(prevProps, nextProps))    .forEach((name) => {      const eventType = name.toLowerCase().substring(2);      dom.addEventListener(eventType, nextProps[name]);    });}

第四步:render阶段

//render阶段function performUnitOfWork(fiber) {  if (!fiber.dom) {    fiber.dom = createDom(fiber);  }  const elements = fiber.props.children;  reconcileChildren(fiber, elements);  if (fiber.child) {    return fiber.child;  }  let nextFiber = fiber;  while (nextFiber) {    if (nextFiber.sibling) {      return nextFiber.sibling;    }    nextFiber = nextFiber.parent;  }}//调协节点function reconcileChildren(wipFiber, elements) {  let index = 0;  let oldFiber = wipFiber.alternate && wipFiber.alternate.child;  let prevSibling = null;  while (index < elements.length || (oldFiber !== null && oldFiber !== undefined)) {    const element = elements[index];    let newFiber = null;    const sameType = oldFiber && element && element.type === oldFiber.type;    if (sameType) {      newFiber = {        type: oldFiber.type,        props: element.props,        dom: oldFiber.dom,        parent: wipFiber,        alternate: oldFiber,        effectTag: "UPDATE",      };    }    if (element && !sameType) {      newFiber = {        type: element.type,        props: element.props,        dom: null,        parent: wipFiber,        alternate: null,        effectTag: "PLACEMENT",      };    }    if (oldFiber && !sameType) {      oldFiber.effectTag = "DELETION";      deletions.push(oldFiber);    }    if (oldFiber) {      oldFiber = oldFiber.sibling;    }    if (index === 0) {      wipFiber.child = newFiber;    } else if (element) {      prevSibling.sibling = newFiber;    }    prevSibling = newFiber;    index++;  }}

相干参考视频解说:进入学习

第五步:commit阶段

//commit阶段function commitRoot() {  deletions.forEach(commitWork);  commitWork(wipRoot.child);  currentRoot = wipRoot;  wipRoot = null;}//操作实在domfunction commitWork(fiber) {  if (!fiber) {    return;  }  const domParent = fiber.parent.dom;  if (fiber.effectTag === "PLACEMENT" && fiber.dom !== null) {    domParent.appendChild(fiber.dom);  } else if (fiber.effectTag === "UPDATE" && fiber.dom !== null) {    updateDom(fiber.dom, fiber.alternate.props, fiber.props);  } else if (fiber.effectTag === "DELETION") {    domParent.removeChild(fiber.dom);  }  commitWork(fiber.child);  commitWork(fiber.sibling);}

第六步:开始调度

//渲染开始的入口function render(element, container) {  wipRoot = {    dom: container,    props: {      children: [element],    },    alternate: currentRoot,  };  deletions = [];  nextUnitOfWork = wipRoot;}//调度函数function workLoop(deadline) {  let shouldYield = false;  while (nextUnitOfWork && !shouldYield) {    //render阶段    nextUnitOfWork = performUnitOfWork(nextUnitOfWork);    shouldYield = deadline.timeRemaining() < 1;  }  if (!nextUnitOfWork && wipRoot) {    commitRoot(); //commit阶段  }  requestIdleCallback(workLoop); //闲暇调度}requestIdleCallback(workLoop);

残缺代码

//创立elementfunction createElement(type, props, ...children) {  return {    type,    props: {      ...props,      children: children.map((child) => (typeof child === "object" ? child : createTextElement(child))),    },  };}//创立text类型function createTextElement(text) {  return {    type: "TEXT_ELEMENT",    props: {      nodeValue: text,      children: [],    },  };}//创立domfunction createDom(fiber) {  const dom = fiber.type === "TEXT_ELEMENT" ? document.createTextNode("") : document.createElement(fiber.type);  updateDom(dom, {}, fiber.props);  return dom;}const isEvent = (key) => key.startsWith("on");const isProperty = (key) => key !== "children" && !isEvent(key);const isNew = (prev, next) => (key) => prev[key] !== next[key];const isGone = (prev, next) => (key) => !(key in next);//更新节点属性function updateDom(dom, prevProps, nextProps) {  //删除老的事件  Object.keys(prevProps)    .filter(isEvent)    .filter((key) => !(key in nextProps) || isNew(prevProps, nextProps)(key))    .forEach((name) => {      const eventType = name.toLowerCase().substring(2);      dom.removeEventListener(eventType, prevProps[name]);    });  // 删除旧属性  Object.keys(prevProps)    .filter(isProperty)    .filter(isGone(prevProps, nextProps))    .forEach((name) => {      dom[name] = "";    });  // 设置新属性  Object.keys(nextProps)    .filter(isProperty)    .filter(isNew(prevProps, nextProps))    .forEach((name) => {      dom[name] = nextProps[name];    });  // 减少新事件  Object.keys(nextProps)    .filter(isEvent)    .filter(isNew(prevProps, nextProps))    .forEach((name) => {      const eventType = name.toLowerCase().substring(2);      dom.addEventListener(eventType, nextProps[name]);    });}//commit阶段function commitRoot() {  deletions.forEach(commitWork);  commitWork(wipRoot.child);  currentRoot = wipRoot;  wipRoot = null;}//操作实在domfunction commitWork(fiber) {  if (!fiber) {    return;  }  const domParent = fiber.parent.dom;  if (fiber.effectTag === "PLACEMENT" && fiber.dom !== null) {    domParent.appendChild(fiber.dom);  } else if (fiber.effectTag === "UPDATE" && fiber.dom !== null) {    updateDom(fiber.dom, fiber.alternate.props, fiber.props);  } else if (fiber.effectTag === "DELETION") {    domParent.removeChild(fiber.dom);  }  commitWork(fiber.child);  commitWork(fiber.sibling);}let nextUnitOfWork = null;let currentRoot = null;let wipRoot = null;let deletions = null;//渲染开始的入口function render(element, container) {  wipRoot = {    dom: container,    props: {      children: [element],    },    alternate: currentRoot,  };  deletions = [];  nextUnitOfWork = wipRoot;}//调度函数function workLoop(deadline) {  let shouldYield = false;  while (nextUnitOfWork && !shouldYield) {    //render阶段    nextUnitOfWork = performUnitOfWork(nextUnitOfWork);    shouldYield = deadline.timeRemaining() < 1;  }  if (!nextUnitOfWork && wipRoot) {    commitRoot(); //commit阶段  }  requestIdleCallback(workLoop); //闲暇调度}requestIdleCallback(workLoop);//render阶段function performUnitOfWork(fiber) {  if (!fiber.dom) {    fiber.dom = createDom(fiber);  }  const elements = fiber.props.children;  reconcileChildren(fiber, elements);  if (fiber.child) {    return fiber.child;  }  let nextFiber = fiber;  while (nextFiber) {    if (nextFiber.sibling) {      return nextFiber.sibling;    }    nextFiber = nextFiber.parent;  }}//调协节点function reconcileChildren(wipFiber, elements) {  let index = 0;  let oldFiber = wipFiber.alternate && wipFiber.alternate.child;  let prevSibling = null;  while (index < elements.length || (oldFiber !== null && oldFiber !== undefined)) {    const element = elements[index];    let newFiber = null;    const sameType = oldFiber && element && element.type === oldFiber.type;    if (sameType) {      newFiber = {        type: oldFiber.type,        props: element.props,        dom: oldFiber.dom,        parent: wipFiber,        alternate: oldFiber,        effectTag: "UPDATE",      };    }    if (element && !sameType) {      newFiber = {        type: element.type,        props: element.props,        dom: null,        parent: wipFiber,        alternate: null,        effectTag: "PLACEMENT",      };    }    if (oldFiber && !sameType) {      oldFiber.effectTag = "DELETION";      deletions.push(oldFiber);    }    if (oldFiber) {      oldFiber = oldFiber.sibling;    }    if (index === 0) {      wipFiber.child = newFiber;    } else if (element) {      prevSibling.sibling = newFiber;    }    prevSibling = newFiber;    index++;  }}const React = {  createElement,  render,};const container = document.getElementById("root");const updateValue = (e) => {  rerender(e.target.value);};const rerender = (value) => {  const element = (    <div>      <input onInput={updateValue} value={value} />      <h2>Hello {value}</h2>    </div>  );  React.render(element, container);};rerender("World");