index.js
import React from "./react";// 渲染 字符串、 jsx、 类组件...class SubCounter {componentWillMount() {console.log("子组件将要挂载");}componentDidMount() {console.log("子组件已挂载✔");}render() {return "嘿嘿"}}class Counter extends React.Component {constructor(props) {super(props);this.state = {number: 1}}componentWillMount() {console.log("父组件将要挂载");}componentDidMount() {console.log("父组件已挂载✔");}render() {console.log('name:', this.props.name);// return this.state.number// return React.createElement(SubCounter, { name: 1 })return (<SubCounter />)/* return (<div className="container"><h1><span>设备枚举示例</span></h1></div>) */}}/*React.createElement(Counter, {name: "xixi"});*//* function say() {alert(1)} */// let ele = <div>xiao</div>// let ele = React.createElement('div', {name: 'xixi' }, 'hello', React.createElement('button', {onclick: say }, '123'))// console.log('ele', ele);React.render(/* 'hello' *//* ele *//* <Counter name="xixi"></Counter> */React.createElement(Counter, {name: "xixi"}),document.getElementById('root'))
react
index.js
import $ from 'jquery'import createReactUnit from "./unit.js";import createElement from './element'import Component from './component'let React = {render,createElement,Component,nextRootIndex: 0}function render(ele, container) {// 工厂函数处理不同的类型,创建并返回对应的react元素实例let createReactUnitInstance = createReactUnit(ele)let markUp = createReactUnitInstance.getMarkUp(React.nextRootIndex)// console.log("markUp===", markUp);// let markUp = `<span data-reactid=${React.nextRootIndex}>${ele}</span>`;$(container).html(markUp)// 触发 DOM挂载完成的方法$(document).trigger('mounted') // 所有组件都ok了}export default React;
util.js
import $ from 'jquery'class Unit {constructor(ele) {// 通过父类保存参数this.curEle = ele}}// 渲染 文本 组件class ReactTextUnit extends Unit {getMarkUp(rootId) {this._rootId = rootIdreturn `<span data-reactid=${rootId}>${this.curEle}</span>`;}}// 渲染 jsx 组件class ReactNativeUnit extends Unit {getMarkUp(rootId) {this._rootId = rootIdlet { type, props } = this.curEle;let tagStart = `<${type} data-reactid="${rootId}"`let tagEnd = `</${type}>`let contentStr = ''for (const propName in props) {if (propName.startsWith('on')) {let eventType = propName.slice(2).toLowerCase()// 事件委托$(document).on(eventType, `[data-reactid="${rootId}"]`, props[propName])} else if (propName === 'children') {contentStr = props[propName].map((child, idx) => {let childInstance = createReactUnit(child)return childInstance.getMarkUp(`${rootId}.${idx}`)}).join('')} else {tagStart += ` ${propName}="${props[propName]}"`}}return tagStart + '>' + contentStr + tagEnd}}// 渲染 类组件class ReactCompositUnit extends Unit {getMarkUp(rootId) {this._rootId = rootIdlet { type: Component, props } = this.curElelet componentInstance = new Component(props)// 创建实例后,即将挂载componentInstance.componentWillMount && componentInstance.componentWillMount()// 调用 render 后返回的结果let reactComponentRenderer = componentInstance.render()// 递归渲染 返回的结果 (先序深度优先, 递归树)let reactCompositUnit = createReactUnit(reactComponentRenderer)// console.log("reactCompositUnit", reactCompositUnit);let markUp = reactCompositUnit.getMarkUp(rootId)// console.log("markUp", markUp);// 深层组件先挂载完成,(在递归之后执行,由内而外)$(document).on('mounted', () => {componentInstance.componentDidMount && componentInstance.componentDidMount()})return markUp}}function createReactUnit(ele) {if (typeof ele === 'string' || typeof ele === 'number') {return new ReactTextUnit(ele)}if (typeof ele === 'object' && typeof ele.type === 'string') {return new ReactNativeUnit(ele)}if (typeof ele === 'object' && typeof ele.type == 'function') {return new ReactCompositUnit(ele)}}export default createReactUnit
element.js


class Element {constructor(type, props) {this.type = typethis.props = props}}function createElement(type, props, ...children) {props = props || {}props.children = childrenreturn new Element(type, props)}// 返回虚拟domexport default createElement
component.js
class Component {constructor(props) {this.props = props}setState() {console.log("更新");}}export default Component
效果:
