在上一篇文章的基础上添加处理类组件渲染。

1、改造index.js,实现一个类组件

  1. // index.js
  2. import React from './react';
  3. import ReactDOM from './react-dom';
  4. class Counter extends React.Component {
  5. constructor(props) {
  6. super(props)
  7. this.state = { number: 0, name: this.props.name }
  8. }
  9. handleClick = () => {
  10. this.setState({
  11. number: this.state.number + 1
  12. })
  13. }
  14. render() {
  15. return (
  16. <div>
  17. {this.state.name}
  18. <div>{this.state.number}</div>
  19. <button onClick={this.handleClick}>增加</button>
  20. </div>
  21. )
  22. }
  23. }
  24. ReactDOM.render(<Counter name="计算器" />, document.getElementById('root'));

2、实现类组件继承的Component父类

  1. // Component.js
  2. import { createDom } from './react-dom'
  3. class Component {
  4. static isReactComponent = true // 标记类组件
  5. constructor(props) {
  6. this.props = props
  7. this.state = {}
  8. }
  9. render() {
  10. throw new Error("此方法为抽象方法,需要子类实现")
  11. }
  12. }
  13. export default Component

3、将Component放在react对象上

  1. // react.js
  2. import Component from "./Component";
  3. const React = { createElement, Component }

4、类组件挂载逻辑处理

4.1 根据类组件标记判断是否为类组件

image.png

4.2 mountClassComponent方法处理

  1. /**
  2. * 挂载类组件
  3. * @param {*} vdom 类组件虚拟dom
  4. */
  5. function mountClassComponent(vdom) {
  6. const { type, props } = vdom
  7. // 创建类的实例
  8. const classInstance = new type(props)
  9. // 调用render方法,返回要渲染的虚拟dom对象
  10. const renderVdom = classInstance.render()
  11. // 根据虚拟dom创建真实dom对象
  12. const dom = createDom(renderVdom)
  13. // 为以后类组件更新做准备,把真实dom挂载到实例上
  14. classInstance.dom = dom
  15. return dom
  16. }

5、类组件更新逻辑处理

5.1 更新方法setState实现

  1. // Component.js
  2. setState(partialState) {
  3. const state = this.state
  4. // 新的state和旧的state合并
  5. this.state = { ...state, ...partialState };
  6. const newVdom = this.render()
  7. updateClassComponent(this, newVdom)
  8. }
  9. function updateClassComponent(classInstance, newVdom) {
  10. const oldDom = classInstance.dom // 取出类组件上次渲染出来的真实dom
  11. // 创建新的DOM
  12. const newDom = createDom(newVdom)
  13. // 新的替换老的
  14. oldDom.parentNode.replaceChild(newDom, oldDom)
  15. classInstance.dom = newDom
  16. }

5.2 更新新的dom

react-dom.js文件updateProps方法增加对属性方法的判断
image.png

6、实现效果

image.png

7、源代码

本文地址:https://gitee.com/linhexs/react-write/tree/3.react-ClassComponent-render/