手动实现一个React(系列一)

262 阅读2分钟

1.实现React

- 首先使用webpack或者parcel(使用文档:  [https://zh.parceljs.org/getting_started.html]() )搭建环境
- 这时候我们在src目录下新建React.js文件,手动创建
  let React = {}
  React.createElement = (type,attrs,...children) => {
      if(!type) {
          return
      }
      return {
          type,
          attrs,
          children
      }
  }
  export default React
  上述代码中,type指的是标签类型,attrs指的是值,children是子级
  如:
  <div id="app">
    <span>hello react</span>
  </div>

这时候我们就可以在index.js中引入React了,怎么样,是不是很简单

2.实现React-DOM

接下来就是第二步,实现虚拟dom的渲染,同样在src目录下新建一个react-dom.js文件
function ReactDOM(vnode, contanier) {
  let element;
  const { type, attrs, children } = vnode;
  
  //1.判断DOM是否是文本节点,是 则创建文本节点,否则就创建DOM节点
  
  if (typeof vnode === "string") {
    element = document.createTextNode(vnode);
  } else {
    element = document.createElement(type);
  }

   //2.将attrs塞进DOM
    
  setAttribute(element, attrs);
    
 //3.在页面上显示
  contanier.appendChild(element);
 
 //这里是判断是否有子级,有则需要递归render逐个塞进element中
  if (children && children.length) {
    children.forEach((node) => {
      ReactDOM(node, element);
    });
  }
}

//实现一个setAttribute方法
    1.是否存在值,存在则进行下一步判断,否则return
    2.值分为三类,一种是正常的如id等,一种是className,另一种是style
    
function setAttribute(element, attrs) {
  if (!element || !attrs) {
    return;
  }

  Object.keys(attrs).forEach((attr) => {
    const value = attrs[attr];
    
    if (attr === "className") {
      element.setAttribute("class", value);
    } else if (attr === "style") {
      if (typeof value === "string") {
        element.style.cssText = value;
      } else if (isObject(value)) {
        let str = "";
        Object.keys(value).forEach((ele) => {
          str += ele + ":" + value[ele] + ";";
          element.style.cssText = str;
        });
      }
    } else {
      element.setAttribute(attr, value);
    }
  });
}

//判断是否为对象
function isObject(obj) {
  return Object.prototype.toString.call(obj) === "[object Object]";
}

export default ReactDOM;

到这里就基本实现了react1.0版本,在index.js中我们来使用一下吧

import React from './src/react'
import ReactDOM from './src/react_-dom'

ReactDOM(
  <div id="app" className="app-class">
    oioioio
    <div
      id="span"
      className="span-class"
      style={{ color: "#f00", width: "100px" }}
    >
      span
    </div>
  </div>,
  document.getElementById("root")
);

好了,看到这里是不是感觉很简单呢,那就动手试一下吧,后续将更新系列二,给它加入生命周期以及事件