1. diff-更新 children

本节课我们来学习一下mini-react中的更新和删除,核心就是当type不一致删除旧的创建新的。

举个例子如下图

  • div变成p

添加测试代码App.jsx

tsx 复制代码
import React from './core/React.js';
​
let showBar = false
​
function Counter({ num }) {
  const Foo = <div>foo</div>
  const Bar = <p>bar</p>
​
  function handleShowBar() {
    showBar = !showBar
    React.update()
  }
​
  return <div>
    Counter
    <div>{showBar ? Bar : Foo}</div>
    <button onClick={handleShowBar}>show bar</button>
  </div>
}
​
function App() {
  return <div>
    hi-mini-react
    <Counter></Counter>
  </div>
}
export default App;

现在没有实现删除,发现效果如下图

删除策略,把需要删除的节点收集起来,之后再commit的时候统一删除

  • 在initChildren函数里面push进deletions数组
tsx 复制代码
function initChildren(fiber, children) {
  ts
    children.forEach((child, index) => {
        const isSameType = oldFiber && oldFiber.type === child.type
        let newFiber
        if (isSameType) {
            //update
            newFiber = {
                type: child.type,
                props: child.props,
                child: null,
                parent: fiber,
                sibling: null,
                dom: oldFiber.dom,
                effectTag: "update",
                alternate: oldFiber
            }
        } else {
            newFiber = {
                type: child.type,
                props: child.props,
                child: null,
                parent: fiber,
                sibling: null,
                dom: null,
                effectTag: "placement"
            }
            if (oldFiber) {
                console.log('oldFiberShouldDelete', oldFiber)
                deletions.push(oldFiber)
             }
        }
    })
}

在commitRoot的时候删除

tsx 复制代码
function commitRoot() {
    deletions.forEach(commitDeletion)
    commitWork(wipRoot.child)
    currentRoot = wipRoot
    wipRoot = null
    deletions = []
}
​
function commitDeletion(fiber) {
    fiber.parent.dom.removeChild(fiber.dom)
}
​
  • 此再去点击发现没有问题了

特别处理function component的问题,先修改App.jsx

tsx 复制代码
import React from './core/React.js';
​
let showBar = false
​
function Counter({ num }) {
  const Foo = () => <div>foo</div>
  const Bar = () => <p>bar</p>
​
  function handleShowBar() {
    showBar = !showBar
    React.update()
  }
​
  return <div>
    Counter
    <div>{showBar ? <Bar /> : <Foo />}</div>
    <button onClick={handleShowBar}>show bar</button>
  </div>
}
​
function App() {
  return <div>
    hi-mini-react
    <Counter></Counter>
  </div>
}
export default App;

点击按钮发现报错

打断点进行调试发现fiber.dom为null,我们需要删除fiber.child这个div

tsx 复制代码
function commitDeletion(fiber) {
    let fiberParent = fiber.parent
    while (!fiberParent.dom) {
        fiberParent = fiberParent.parent
    }
    if (fiber.dom) {
        fiberParent.dom.removeChild(fiber.dom)
    } else {
        commitDeletion(fiber.child)
    }
}
​
相关推荐
闲蛋小超人笑嘻嘻7 分钟前
localStorage用法详解
前端
Swift社区10 分钟前
用 RN 的渲染模型,反推 Vue 列表的正确拆分方式
前端·javascript·vue.js
Mr_chiu10 分钟前
微前端从入门到精通:Vue开发者的大型应用架构演进指南
前端·架构
Violet_YSWY14 分钟前
Vue-Pinia defineStore 语法结构
前端·javascript·vue.js
全栈陈序员14 分钟前
v-if 和 v-for 的优先级是什么?
前端·javascript·vue.js·学习·前端框架·ecmascript
xinyu_Jina16 分钟前
Info Flow:大规模列表渲染中的UI虚拟化、数据懒-加载与前端性能工程
前端·ui
GISer_Jing19 分钟前
JD AI全景:未来三年带动形成万亿规模的人工智能生态
前端·人工智能·aigc
全栈陈序员20 分钟前
你对 SPA 单页面应用的理解?它的优缺点分别是什么?如何实现 SPA 应用?
前端·vue.js·学习·前端框架·vue
我是伪码农24 分钟前
动态表格案例
前端·javascript·html
我是伪码农25 分钟前
随机点名案例
前端·css·css3