【系列 3】react 运行类函数组件

206 阅读1分钟

react 运行类函数组件

import React from "./react";
import ReactDOM from "./react-dom";

class ClassComponent extends React.Component {
  render() {
    return (
      <div className="title" style={{ color: "red" }}>
        <h1>{this.props.name}</h1>
        <h3>{this.props.children}</h3>
      </div>
    );
  }
}

ReactDOM.render(
  <ClassComponent name="hello">world</ClassComponent>,
  document.getElementById("root")
);

1. jsx 转 js 代码

上述代码编译时通过 babel 插件转译成如下代码:

class ClassComponent extends React.Component {
  render() {
    return React.createElement("div", {
      className: "title",
      style: {
        color: "red"
      }
    },
    React.createElement("h1", null, this.props.name),
    React.createElement("h3", null, this.props.children));
  }

}

ReactDOM.render(
    React.createElement(ClassComponent, {
      name: "hello"
    }, "world"),
    document.getElementById("root")
);

简写一下 React.Component:

export class Component {
  static isReactComponent = true; // 标记是一个类组件 目的: 让 React.createElement 知道 参数1 是类组件
  constructor(props) {
    this.props = props;
  }
}

const React = {
  Component
};

2. ReactDOM.render 参数1 接收类组件 vdom

function render(vdom, container) {
  const newDOM = createDOM(vdom);  // 生成节点
  container.appendChild(newDOM);   // 挂载节点
}

function createDOM(vdom) {
  if (typeof type === "function") {
    // + 添加一个是继承 React.Component 类函数的判断
    if (type.isReactComponent) {
      return mountClassComponent(vdom);
    }
  } else {
    dom = document.createElement(type);
  }
  
  return dom
}

// + 添加一个方法:执行这个类函数组件上的 render 方法
function mountClassComponent(vdom) {
  const { type, props } = vdom;
  const classInstance = new type(props);
  const renderVdom = classInstance.render(); // 执行 render
  const dom = createDOM(renderVdom);         // 返回 html 节点
  return dom;
}

const ReactDOM = {
  render
};

最终效果:

此时打开浏览器我们就看见了 hello world

image.png

本系列代码链接
GitHubgithub.com/shunyue1320…
Giteegitee.com/shunyue/min…