Skip to content

shenqil/react-learn

This branch is 1 commit ahead of main.

Folders and files

NameName
Last commit message
Last commit date

Latest commit

author
shenqi.lv
Feb 22, 2022
8146ea0 · Feb 22, 2022

History

2 Commits
Feb 1, 2022
Feb 22, 2022
Feb 1, 2022
Feb 1, 2022
Feb 1, 2022
Feb 1, 2022
Feb 22, 2022
Feb 1, 2022
Feb 1, 2022
Feb 1, 2022
Feb 1, 2022
Feb 1, 2022
Feb 1, 2022
Feb 1, 2022
Feb 1, 2022

Repository files navigation

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

  • 可以看到vnode 主要由 type,key,ref,props组成
  • vnode如果是HTMLElement, type 就是HTMLElement的类型
  • vnode如果是文本,则直接放入字符串
  • vnode如果是FunctionComponent,ClassComponent, type则是一个函数
  • ClassComponent组件的prototype上会有 isReactComponent属性,用来区分class组件和函数组件

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;
}
  • 根据上面type,大致把组件分为三类,HTMLElement,ReactComponent,textElement
  • HTMLElement,直接使用 document.createElement 创建即可,然后继续遍历子元素,执行render,同时将props挂载在node上
  • ReactComponent,函数组件直接执行,类组件先实例化后,执行内部的render函数,将返回的jsx,当作参数递归执行createNode
  • textElement,直接使用document.createTextNode

2.3 类组件 Component

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

export default { Component };
  • 将props绑定到this中
  • 在prototype上标记自己是ReactComponet

3.最终结果

image.png 源码

About

react学习雍熙

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published