React深入4 - 源码初探(jsx)

2022-02-27  本文已影响0人  申_9a33

1. 先创一个包含函数组件,class组件,和html各种元素的jsx

// src\main.tsx

import React, { Component } from 'react';
import { render } from 'react-dom';
import './index.scss';

interface IProps{
  name:string
}

function FuncationComponent(props:IProps) {
  return (
    <div className="border">
      <p>{props.name}</p>
    </div>
  );
}

// eslint-disable-next-line react/prefer-stateless-function
class ClassComponent extends Component<IProps> {
  render(): React.ReactNode {
    return (
      <div className="border">
        <p>{this.props.name}</p>
      </div>
    );
  }
}

const jsx = (
  <div className="border">
    <h1>jsx title</h1>
    <a href="https://www.baidu.com/">链接</a>
    <FuncationComponent name="FuncationComponent" />
    <ClassComponent name="ClassComponent" />
  </div>
);

render(jsx, document.getElementById('root'));
image.png

2. 'react-dom' 里面的 render

2.1 接受两个参数 jsx (vnode)和 原生element,我们打印vnode

// src\react\react-dom.ts

export function render(vnode:any, container:any) {
  console.log(vnode, 'vnode');
  // vnode -> node
  const node = createNode(vnode);

  // node -> container
  container.appendChild(node);
}
image.png

2.2 createNode 将vnode 转换为node

function createNode(vnode:any):any {
  let node;

  const { type, props } = vnode;

  switch (true) {
    case isString(type): {
      // HTMLElement 元素
      node = document.createElement(type); // 根据类型创建真实dom
      reconcileChildren(node, props.children); // 继续渲染子元素
      updateNode(node, props); // 将属性挂载在node上
      break;
    }

    case isFunction(type):
      // React函数组件,类组件
      node = type.prototype.isReactComponent
        ? updateClassComponent(vnode)
        : updateFunctionComponent(vnode);
      break;

    case type === undefined:
      // 普通文本
      node = document.createTextNode(vnode);
      break;

    default:
      node = document.createTextNode('');
      break;
  }

  return node;
}

2.3 类组件 Component

export function Component(props:any) {
  this.props = props;
}
Component.prototype.isReactComponent = {};

export default { Component };

3.最终结果

image.png
源码
上一篇 下一篇

猜你喜欢

热点阅读