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)
    }
}
​
相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万2 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋2 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁2 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95272 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大2 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师2 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学2 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端