Skip to content

Commit

Permalink
六: 2.实现 setState
Browse files Browse the repository at this point in the history
  • Loading branch information
zh-lx committed Nov 10, 2021
1 parent 6144a2d commit a0e9d46
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/index.js
@@ -1,4 +1,4 @@
import { Component } from 'react';
import { Component } from './mini-react/react';
import ReactDOM from './mini-react/react-dom';
import './index.css';

Expand Down
35 changes: 31 additions & 4 deletions src/mini-react/fiber.js
Expand Up @@ -17,6 +17,16 @@ export function getDeletions() {
return deletions;
}

// 触发渲染
export function commitRender() {
workInProgressRoot = {
stateNode: currentRoot.stateNode, // 记录对应的真实 dom 节点
element: currentRoot.element,
alternate: currentRoot,
};
nextUnitOfWork = workInProgressRoot;
}

// 创建 rootFiber 作为首个 nextUnitOfWork
export function createRoot(element, container) {
workInProgressRoot = {
Expand Down Expand Up @@ -44,10 +54,7 @@ function performUnitOfWork(workInProgress) {
// 当前 fiber 对应 React 组件时,对其 return 迭代
if (type.prototype.isReactComponent) {
// 类组件
const { props, type: Comp } = workInProgress.element;
const component = new Comp(props);
const jsx = component.render();
children = [jsx];
updateClassComponent(workInProgress);
} else {
// 函数组件
const { props, type: Fn } = workInProgress.element;
Expand Down Expand Up @@ -87,6 +94,26 @@ function performUnitOfWork(workInProgress) {
}
}

// 类组件的更新
function updateClassComponent(fiber) {
let jsx;
if (fiber.alternate) {
// 有旧组件,复用
const component = fiber.alternate.component;
fiber.component = component;
component._UpdateProps(fiber.element.props);
jsx = component.render();
} else {
// 没有则创建新组件
const { props, type: Comp } = fiber.element;
const component = new Comp(props);
fiber.component = component;
jsx = component.render();
}

reconcileChildren(fiber, [jsx]);
}

// 处理循环和中断逻辑
function workLoop(deadline) {
let shouldYield = false;
Expand Down
28 changes: 28 additions & 0 deletions src/mini-react/react.js
@@ -0,0 +1,28 @@
import { commitRender } from './fiber';
export class Component {
constructor(props) {
this.props = props;
}
}
Component.prototype.isReactComponent = true;

Component.prototype.setState = function (param) {
if (typeof param === 'function') {
const result = param(this.state, this.props);
this.state = {
...this.state,
...result,
};
} else {
this.state = {
...this.state,
...param,
};
}

commitRender();
};

Component.prototype._UpdateProps = function (props) {
this.props = props;
};

0 comments on commit a0e9d46

Please sign in to comment.