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)
    }
}
​
相关推荐
学嵌入式的小杨同学8 小时前
从零打造 Linux 终端 MP3 播放器!用 C 语言实现音乐自由
linux·c语言·开发语言·前端·vscode·ci/cd·vim
weixin_425543739 小时前
TRAE CN3.3.25 构建的Electron简易DEMO应用
前端·typescript·electron·vite·nestjs
Mr Xu_10 小时前
【Vue3 + ECharts 实战】正确使用 showLoading、resize 与 dispose 避免内存泄漏
前端·信息可视化·vue·echarts
0思必得010 小时前
[Web自动化] Selenium设置相关执行文件路径
前端·爬虫·python·selenium·自动化
雯0609~10 小时前
hiprint:实现项目部署与打印1-官网提供普通html版本
前端·html
不绝19110 小时前
UGUI——进阶篇
前端
Exquisite.11 小时前
企业高性能web服务器(4)
运维·服务器·前端·网络·mysql
2501_9445255411 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 账户详情页面
android·java·开发语言·前端·javascript·flutter
2601_9498574311 小时前
Flutter for OpenHarmony Web开发助手App实战:快捷键参考
前端·flutter
wangdaoyin201012 小时前
若依vue2前后端分离集成flowable
开发语言·前端·javascript