// 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'));
// 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);
}
- 可以看到vnode 主要由 type,key,ref,props组成
- vnode如果是
HTMLElement
, type 就是HTMLElement
的类型 - vnode如果是文本,则直接放入字符串
- vnode如果是FunctionComponent,ClassComponent, type则是一个函数
- ClassComponent组件的prototype上会有
isReactComponent
属性,用来区分class组件和函数组件
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
export function Component(props:any) {
this.props = props;
}
Component.prototype.isReactComponent = {};
export default { Component };
- 将props绑定到this中
- 在prototype上标记自己是ReactComponet