构建你自己的 React
Build Your Own React

原始链接: https://pomb.us/build-your-own-react/

这段代码实现了一个简化的类似React的渲染系统,名为“Didact”。它专注于创建虚拟DOM(使用`createElement`和`createTextElement`)并根据变化有效地更新真实DOM。 核心过程包括: 1. **`createElement`**: 创建虚拟DOM节点(fiber)。 2. **`render`**: 启动渲染过程,通过`requestIdleCallback`调度工作以提高性能。 3. **`workLoop` & `performUnitOfWork`**: 这些函数迭代地构建DOM树,创建DOM节点(`createDom`)并应用属性(`updateDom`)。 4. **`reconcileChildren`**: 比较新的虚拟DOM与旧的虚拟DOM,以识别变化(添加、更新、删除)。 5. **`commitWork`**: 将更改应用于实际DOM,处理插入、更新和删除。 该系统使用“effect标签”(PLACEMENT, UPDATE, DELETION)来跟踪必要的DOM操作,并通过仅更改不同之处来优化更新。它的目标是模仿React的核心概念:虚拟DOM和高效的协调。

Hacker News 新闻 | 过去 | 评论 | 提问 | 展示 | 工作 | 提交 登录 自己构建 React (pomb.us) 22 分,by howToTestFE 4 小时前 | 隐藏 | 过去 | 收藏 | 4 评论 agarren 1 小时前 | 下一个 [–] 这是一次极好的展示。它让我想起了 BackboneJS 过去使用的注释源代码/网站,但这个是交互式的。 真是太棒了!回复 theturtletalks 1 分钟前 | 父评论 | 下一个 [–] Pomber 是 CodeHike 的创始人,你看到的代码块动画是由它驱动的!我们用 CodeHike 来做文档教程,它更容易理解。回复 agumonkey 1 小时前 | 父评论 | 上一个 | 下一个 [–] 如果我没记错的话,CoffeeScript 文档也使用了相同的系统,非常好。回复 a456463 1 小时前 | 上一个 [–] 很棒的网站和故事呈现方式。喜欢它!回复 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 申请 YC | 联系 搜索:
相关文章

原文

function createElement(type, props, ...children) {

children: children.map(child =>

typeof child === "object"

: createTextElement(child)

function createTextElement(text) {

function createDom(fiber) {

fiber.type == "TEXT_ELEMENT"

? document.createTextNode("")

: document.createElement(fiber.type)

updateDom(dom, {}, fiber.props)

const isEvent = key => key.startsWith("on")

const isProperty = key =>

key !== "children" && !isEvent(key)

const isNew = (prev, next) => key =>

const isGone = (prev, next) => key => !(key in next)

function updateDom(dom, prevProps, nextProps) {

isNew(prevProps, nextProps)(key)

.filter(isGone(prevProps, nextProps))

.filter(isNew(prevProps, nextProps))

dom[name] = nextProps[name]

.filter(isNew(prevProps, nextProps))

deletions.forEach(commitWork)

commitWork(wipRoot.child)

function commitWork(fiber) {

const domParent = fiber.parent.dom

fiber.effectTag === "PLACEMENT" &&

domParent.appendChild(fiber.dom)

fiber.effectTag === "UPDATE" &&

} else if (fiber.effectTag === "DELETION") {

domParent.removeChild(fiber.dom)

commitWork(fiber.sibling)

function render(element, container) {

let nextUnitOfWork = null

function workLoop(deadline) {

while (nextUnitOfWork && !shouldYield) {

nextUnitOfWork = performUnitOfWork(

shouldYield = deadline.timeRemaining() < 1

if (!nextUnitOfWork && wipRoot) {

requestIdleCallback(workLoop)

requestIdleCallback(workLoop)

function performUnitOfWork(fiber) {

fiber.dom = createDom(fiber)

const elements = fiber.props.children

reconcileChildren(fiber, elements)

nextFiber = nextFiber.parent

function reconcileChildren(wipFiber, elements) {

wipFiber.alternate && wipFiber.alternate.child

index < elements.length ||

const element = elements[index]

element.type == oldFiber.type

if (element && !sameType) {

if (oldFiber && !sameType) {

oldFiber.effectTag = "DELETION"

oldFiber = oldFiber.sibling

wipFiber.child = newFiber

prevSibling.sibling = newFiber

return <h1>Hi {props.name}</h1>

const element = <App name="foo" />

const container = document.getElementById("root")

Didact.render(element, container)

联系我们 contact @ memedata.com