手写react

本文详细探讨了React的核心思想,包括jsx转换、虚拟DOM的创建、渲染过程及fiber架构。通过分析`createElement`和`render`函数,揭示了React如何将jsx转化为虚拟DOM并实际渲染到页面。此外,还介绍了React Hooks的工作原理,以及如何在项目中实现基本的state管理和生命周期。学习React源码有助于更深入地理解和优化应用性能。
摘要由CSDN通过智能技术生成

关于react源码,很早就有参阅的想法了,奈何每次实践都是浅尝则止,思考了很久:与其预留时间统一观阅学习,不如手起刀落 现在跟学总结经验;

repo:https://github.com/CNZN/myreact

目的:了解react基本思想,对常用api原理的剖析及实现, 希望对React 的基本逻辑及实现思路有了大概的掌握;

预想困难:
实现流程:基于babel转义的js得到dom虚拟对象,分析creatElement、render的实现

jsx代码

//如若想让babel用自写的js去解析需要加上下面这行
/** @jsx MyReact.createElement */
const element = <div title="foo">hello</div>

babel转译后的代码

"use strict";
//### 这是babelES6转译ES5自动加上的,使用严格模式的意思;
const element = /*#__PURE__*/React.createElement("div", {
  title: "foo"
}, "hello");
//"Pure" 注入支持
//转换后的 ES6 类将使用 /*#__PURE__*/ 进行注释。
//这允许给像 Uglify 和 babel-minify 这样的 minfiers 
//在删除无用代码时提供提示。这些注释也会被添加到其他辅助函数中。

react.createElement是把jsx语法转换为虚拟dom,也就是js对象存于内存中,可以根据入参写一下createElement

1、creatElement

function createElement (type, props, ...children) {
    return {
        type,
         props: {
             ...props,
             children: children.map(child => 
                 typeof child === 'object'
                 ? child
                 : createTextElement(child)
             )
         }
     }
}
function createTextElement (text) {
    return {
        // 判断文本节点
        type: "TEXT_ELEMENT",
        props: {
            nodeValue: text,
            // 无子节点
             children: []
        }
    }
}

2、render
经过createElement之后element的实际值为
在这里插入图片描述
这样的数据格式就再清楚不过了,岂不是和创建路由类似?children里存放子节点,子节点自带属性,且也可能有子节点

function render (element, container) {
    // 这里通过拿到的vdom生成真实dom节点
    const dom = element.type === 'TEXT_ELEMENT'
        ? document.createTextNode("")
        : document.createElement(element.type)
    // 有子节点的话递归
    element.props.children.forEach(child => 
        render(child, dom)
    )

    const isProperty = key => key !== "children"
    Object.keys(element.props)
        .filter(isProperty)
        .forEach(name => {
            // 将属性付给节点
            dom[name] = element.props[name]
        })
    container.appendChild(dom)
}

3、fiber
为了让渲染工作可以随场景而暂停,将渲染工作小化,react设计了fiber,代表着一个数据结构或者一个工作单元。
此处可以理解为浏览器空闲与否会添加一个全局变量,在renderdom的函数中起阀门作用

 // 创建 fiber
 const newFiber = {
     type: element.type,
     props: element.props,
     parent: fiber,
     dom: null,
}

4、hooks
每次使用钩子时(以useState为例),会在初始化时可以接受初始值,且返回初始状态及状态改变的方法,方法可以为函数.
思路大致为

function useState (init) {

	//首先会判断是更新,上一次vdom对象是否有值
	const oldhook = wipFiber.alternate && wipFiber.alternate.hook;

	const hook = {
		state: oldhook ? oldhook.state : init
		//存放状态修改逻辑
		queue: []
	}
	// 从旧的钩子队列中获取所有动作,然后将它们一一应用到新的钩子状态
    const actions = oldHook ? oldHook.queue : []
    actions.forEach(action => {
        hook.state = action(hook.state)
    })

	const setState = behavior => {
		hooks.queue.push(behavior)
	}
	return [hook.state, setState]

}

一揽

学习网址: 英文网页清汤饺子
调试网站

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值