跟着阿崔cxr手搓mini-react

239 阅读2分钟

洋洋得意入门

由于一开始两节课听得感觉很有趣,以为自己可以提前一步解决组件套用以及函数组件兼容,自己现在 createdElement 先加了两个判断

const createdElement = (type, props, ...children) => {
  //判断是否是组件
  if (typeof type === "object") {
    return type;
  }

  //判断是不是函数组件
  if (typeof type === "function") {
    console.log("createdElementFFFFF", type, props, children);
    const elm = {};
    //记录函数组件 用于更新
    functionComponents.push(elm);
    Object.assign(elm, {

      ...type(props),
      updateFunction: () => {
        return type(props);
          // Object.assign(elm,  type(props));
      },
    });

    return elm;
  }

  return {
    type,
    props: {
      ...props,
      children: children.map((child) => {
        return typeof child === "object" ? child : createTextElement(child);
      }),
    },
  };
};

一开始 ,这个方法顺利解决了组件的渲染,洋洋得意的时候,接下来两节课我都没有发现啥不妥,还在纳闷为啥课程中为啥还需要在 commitWork判断fiber有没有dom,为啥我没有这一步也能实行渲染呢?难道我真的是天才?

逐渐感到不对劲

直到上到update 的课程,需要找到当前的fiber 进行函数组件的更新; 在这里我逐渐感到不对劲了,我发现我的方法在调用update时根本没办法找到wipFiber,但是这时候我又想到一个方法,让我的代码也能点击更新页面

image.png 就是在createElement 的时候将每个节点都push 到一个数组里面,当点击更新的时候,遍历所有保存的阶段,调用它的updateFunction 方法重新生成 新的节点

真的碰壁了

到了局部更新组件功能,我的办法彻底失效了,我对于 createdElement 中加入了函数组件的判断直接返回运算结果,其实无异议一开始就让函数组件变成普通的静态组件了,里面的变量 方法啥的都是执行时的状态,以至于update /useState 等都无法取的当前的fiber ,我试图将这个判断进行到底,也困扰了几天都一事无成......

浪子回头

最后我还是老老实实跟着课程的思路来实现min-react,学到最后理解了为什么 函数组件要放到 render 之后再处理,只有放这里才能生成新的fiber树 ,然后才能去比较更新...

最后优化课程代码,再加入了 函数组件使用map的判断 ,静态组件的判断

function createElement(type, props, ...children) {
  // //判断children
  if (Array.isArray(children[0])) {
    //拍平
    children = children.flat();
  }
  if (typeof type === "object") {
    return type
  }
  return {
    type,
    props: {
      ...props,
      children: children.map((child) => {
        const isTextNode =
          typeof child === "string" || typeof child === "number";
        return isTextNode ? createTextNode(child) : child;
      }),
    },
  };
}

实现了课程任务 TODOLIST

image.png

代码仓库: mini-react-study 完成todolist

学习心得

写代码,看清楚,思路清晰很重要,未看清楚瞎写容易事半功倍 你必须全力以赴,才能看起来毫不费力