文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

React怎么更新流程驱动

2023-07-06 04:11

关注

这篇文章主要介绍了React怎么更新流程驱动的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇React怎么更新流程驱动文章都会有所收获,下面我们一起来看看吧。

一、react.createElement和ReactElement元素

首先我们书写的函数式组件、类组件、jsx等代码全部会被babel-react编译成react.createElement()的调用或者jsx()调用(取决于react版本)。

举个栗子:

<div>    <ul>    <li key='1'>1</li>    <li key='2'>2</li>    <li key='3'>3</li>    </ul></div>

转换成

React.createElement('div',null,React.createElement('ul',null,React.createElement(                'li',                {                  key: '1'                },                '1'),React.createElement(                'li',                {                 key: '2'                },                '2'),React.createElement(                'li',                {                        key: '3'                },                '3')));

接下来我们需要知道React.createElement内部到底做了什么?源码位置

内部的实现其实很简单,就是处理传入的type/config/children等参数,再返回一个新的对象。

ReactElement数据结构如下:

  const element = {    $$typeof: REACT_ELEMENT_TYPE,    type,    key,    ref,    props,  };

所以上述栗子的调用结果是下面的树形结构:

{    type: 'div',    key: null,    ref: null,    props: {        children: {                    type: 'ul',                    key: null,                    ref: null,                    props: {                        children: [                                    {                                        type: 'li',                                        key: null,                                        ref: null,                                        props: {                                            children: '1'                                        }                                    },                                    {                                        type: 'li',                                        key: null,                                        ref: null,                                        props: {                                                children: '2'                                        }                                    },                                    {                                        type: 'li',                                        key: null,                                        ref: null,                                        props: {                                               children: '3'                                        }                                    }                                ]                    }        }    }}

到这里就已经完成第一个和第二个小目标

不过在这里要多提一下,上述的树形结构,在react15版本及以前就可以直接拿来diff以及生成页面,不过正如第一篇文章所说,这样会遇到很大的问题(任务过重js执行时间久,影响渲染)。

所以16之后做的事情,就是依据上述的树形结构进行重构,重构出来的fiber数据结构用于满足异步渲染之需

二、双缓存技术

上篇文章中已经介绍了fiber节点的数据结构,这里我们再介绍下fiberRoot以及rootFiber。 fiberRoot源码位置

FiberRoot数据结构:

class FiberRootNode {  current: FiberNode;  container: any | null;  finishedWork: FiberNode | null;  pendingLanes: Lanes;  finishedLane: Lane;  pendingPassiveEffects: PendingPassiveEffects;  constructor(container: any | null, hostRootFiber: FiberNode) {    this.current = hostRootFiber;    this.container = container;    hostRootFiber.stateNode = this;    this.finishedWork = null;    this.pendingLanes = NoLanes;    this.finishedLane = NoLane;    this.pendingPassiveEffects = {      unmount: [],      update: []    };  }}

其中很多属性我们暂时无视,后续涉及到的时候会详细讲解,这里重点关注节点的关系。 rootFiber的数据结构和普通的FiberNode节点区别不大,这里不再赘述~

整个React应用有且只有一个fiberRoot

整个应用中同时存在两棵rootFiber树

当前页面对应的称为currentFiber,另外一颗在内存中构建的称为workInProgressFiber,它们通过alternate属性连接。

fiberRoot中的current指针指向了currentFiber树。

当整个应用更新完成,fiberRoot会修改current指针指向内存中构建好的workInProgressFiber。

图形描述如下:

React怎么更新流程驱动

三、React初始化的执行函数

在mount阶段的时候,应用是需要一个执行函数的,而这个函数就是(源码位置)

    react.createRoot(root).render(<App/>)

源码简化后的代码如下:

    const createRoot = (container: Container) => {            const root = createContainer(container);            return {                render(element: ReactElementType) {                        return updateContainer(element, root);                }            };    };

createRoot会返回一个对象,其中包含了render函数,我们具体看看createContainer做了哪些事情。

const createContainer = (container: Container) => {    // 创建rootFiber    const hostRootFiber = new FiberNode(HostRoot, {}, null);    // 创建fiberRoot    const root = new FiberRootNode(container, hostRootFiber);    hostRootFiber.updateQueue = createUpdateQueue();    return root;};

react.createRoot()在内部会去创建整个应用唯一的fiberRoot和rootFiber,并进行关联。(如上述图形结构)

render内部执行的是updateContainer(),我们查看下内部实现:

const updateContainer = (element: ReactElementType,root: FiberRootNode) => {// mount时const hostRootFiber = root.current;// 添加update任务const lane = requestUpdateLane();const update = createUpdate<ReactElementType | null>(element, lane);enqueueUpdate(hostRootFiber?.updateQueue as UpdateQueue<ReactElementType | null>,update);scheduleUpdateOnFiber(hostRootFiber, lane);return element;};

其中有很多地方我们此时无须关心,但是我们看到内部调用了scheduleUpdateOnFiber, 而这个就是更新流程(schedule(调度)->reconciler(协调)->commit (渲染))的入口。

而这个入口不仅仅在初始化执行函数中render调用会唤起,还有其他的方式:

关于“React怎么更新流程驱动”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“React怎么更新流程驱动”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网行业资讯频道。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯