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)
    }
}
​
相关推荐
mayaairi25 分钟前
Vue2 事件绑定完全指南:从入门到原理
前端·javascript·vue.js
ℋᙚᵐⁱᒻᵉ鲸落6 小时前
移动端滑动手势冲突:overflow: auto导致外层横向滑动失效
前端·javascript·css·vue.js·html
默_笙7 小时前
🎃 前端学了 Next.js,后端该学啥?NestJS 就是 Node 版的蜜雪冰城
前端·javascript
前端snow8 小时前
ai agent --- 实现 openclaw 定时间效果
前端
码云之上9 小时前
换模型之后,Chatbot 为什么要自己做 compact?
前端·agent·前端工程化
星栈9 小时前
自定义 UI-UX-Pro-Max 的 CSV 知识库,把 AI 生成的后台拉回行业该有的样子
前端·agent·weui
研☆香9 小时前
简单的图片上传 删除 预览
前端
ITresearchGuest9 小时前
我用 AI 一小时写了一个世界杯数据可视化平台|前端 VibeCoding 初体验
前端·人工智能·信息可视化
慧一居士11 小时前
Vite项目中使用Less步骤,详细使用示例
前端·css
花间相见11 小时前
【LangChain组件03】—— LangChain Agents 执行与状态:工作流程与状态管理实战
java·前端·langchain