react中state的作用是什么(React中useEffect 与 useLayoutEffect的区别)
react中state的作用是什么
React中useEffect 与 useLayoutEffect的区别目录
- 前置知识
- useEffect
- commitBeforeMutationEffects
- commitMutationEffects
- commitLayoutEffects
- 后续阶段
- useLayoutEffect
- 结论
我们可以将 React 的工作流程划分为几大块:
- render 阶段:主要生成 Fiber节点 并构建出完整的 Fiber树
- commit 阶段:在上一个render 阶段中会在 rootFiber 上生成一条副作用链表,应用的DOM操作就会在本阶段执行
commit阶段的工作主要分为三部分,对应到源码中的函数名是:
- commitBeforeMutationEffects阶段:主要处理执行DOM操作前的一些相关操作
- commitMutationEffects阶段:执行DOM操作
- commitLayoutEffects阶段:主要处理执行DOM操作后的一些相关操作
useEffect 和 useLayoutEffect 的区别主要就在体现在这三个阶段的处理上。结论是:useEffect 会异步地去执行它的响应函数和上一次的销毁函数,而useLayoutEffect 会同步地执行它的响应函数和上一次的销毁函数,即会阻塞住 DOM渲染。
useEffectcommitBeforeMutationEffects
在这个阶段中 useEffect 着重会经历一句话如下:
function commitBeforeMutationEffects() { while (nextEffect$1 !== null) { // 一系列的赋值操作省略,这里的flags应取自对应FunctionComponent的effect的flags,具体实现请看源码 var flags = effect.flags; // 处理生命周期 if ((flags & Snapshot) !== NoFlags) { setCurrentFiber(nextEffect$1); commitBeforeMutationLifeCycles(current, nextEffect$1); resetCurrentFiber(); } // 这个if判断只有 useEffect 为 true,useLayoutEffect 为false if ((flags & Passive) !== NoFlags) { // If there are passive effects, schedule a callback to flush at // the earliest opportunity. if (!rootDoesHavePassiveEffects) { rootDoesHavePassiveEffects = true; // 这里就是 useEffect 异步的原因,DOM操作后React会调度 flushPassiveEffects scheduleCallback(NormalPriority, function () { flushPassiveEffects(); return null; }); } } nextEffect$1 = nextEffect$1.nextEffect; } }
commitMutationEffects
在这个阶段中,React 会进行一系列的DOM节点更新 ,然后会执行一个方法: commitHookEffectListUnmount(HookLayout | HookHasEffect, finishedWork);
那么一个拥有 useEffect 的 Functional Component 在这个阶段是不符合 unmount 的判断逻辑的,所以在这个地方不会做 unmount 操作。
commitLayoutEffects
在这个阶段中,依然有一个很重要的方法存在:commitHookEffectListMount(HookLayout | HookHasEffect, finishedWork);
这个if判断和上一阶段的if判断是一样的,useEffec 在这个判断中不会做任何操作。
后续阶段
在完成了 commitLayoutEffects 后,还有一个操作:
if (rootDoesHavePassiveEffects) { // This commit has passive effects. Stash a reference to them. But don't // schedule a callback until after flushing layout work. rootDoesHavePassiveEffects = false; rootWithPendingPassiveEffects = root; pendingPassiveEffectsLanes = lanes; pendingPassiveEffectsRenderPriority = renderPriorityLevel; }
即把 rootWithPendingPassiveEffects 置为 root ,这么做的原因和第一阶段 commitBeforeMutationEffects 中 useEffect 注册的下一次 flushPassiveEffects 异步调度有关,我们看以下 flushPassiveEffects 的实现:
function flushPassiveEffectsImpl() { if (rootWithPendingPassiveEffects === null) { return false; } // 省略一系列的性能追踪等操作 commitPassiveUnmountEffects(root.current); commitPassiveMountEffects(root, root.current); }
从上述代码段可以看见,useEffect 在第一阶段注册的调度回调会在页面更新后进行 unmount 和 mount 操作。值得一提的是,这个回调中effect的注册时机就是在 commitLayoutEffects 阶段。
useLayoutEffect其实根据我们对 useEffect 的解析来看,就是在 commitMutationEffects 和 commitLayoutEffects 阶段中各自的 if 判断中,useLayoutEffect 是通过if判断的,所以在 commitMutationEffects 阶段中,同步执行了useLayoutEffect 的上一次销毁函数,在 commitLayoutEffects 阶段中,同步执行了 useLayoutEffect 本次的执行函数,并注册上销毁函数。
结论至此,我们粗略地查看了 commit 阶段的代码,分析了以下为什么 useEffect 是异步执行,而 useLayoutEffect 是同步执行,具体的代码我没有太过在文章中贴出来,因为这些都是可变的,真正的流程性的概览和 React 团队设计这一套机制的心智模型需要我们自己在不断调试代码和理解中慢慢去熟悉。
后续自己感兴趣的是 hooks 的实现,其中比较关键的 useReducer 会着重看一下源码,看看能不能写个简易版本的放到支付宝小程序中去实现一个 自定义的支付宝hooks 用于日常生产力开发。
到此这篇关于React中useEffect 与 useLayoutEffect的区别的文章就介绍到这了,更多相关React useEffect useLayoutEffect内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
- react 查看word文件(React实现导入导出Excel文件)
- vue3.0 如何使用useroute(详解vue3中setUp和reactive函数的用法)
- react怎么绑定state(react纯函数组件setState更新页面不刷新的解决)
- react绑定详解(React列表栏及购物车组件使用详解)
- react常用设计模式(提高React界面性能的十个技巧)
- react重点和难点(关于React状态管理的三个规则总结)
- reactnative混合开发教程(教你使用vscode 搭建react-native开发环境)
- react中state的作用是什么(React中useEffect 与 useLayoutEffect的区别)
- react事件绑定的方式和区别(react合成事件与原生事件的相关理解)
- react的事件绑定(React事件绑定的方式详解)
- react基础知识详解(如何深入理解React的ref 属性)
- react app框架(浅谈React原生APP更新)
- react定时任务(手把手带你用React撸一个日程组件)
- reacthooks基础使用(React 小技巧教你如何摆脱hooks依赖烦恼)
- reactnative ios(详解React Native与IOS端之间的交互)
- react动态创建菜单并实现局部刷新(使用react-virtualized实现图片动态高度长列表的问题)
- 痴情男神 吴彦祖 与妻子恋爱8年,结婚10年,家庭幸福美满(痴情男神吴彦祖)
- 成功破圈,小牛电动SQi强势开 跨(小牛电动SQi强势开)
- 挑战新国标电自天花板,九号机械师MMAX 110P深度体验(挑战新国标电自天花板)
- 《满江红》不要只当电影看,学生应该这样做(满江红不要只当电影看)
- 电影《民间怪谈录之走阴人》定档8月5日,开启一场中式惊悚之旅(电影民间怪谈录之走阴人定档8月5日)
- 原创图画书,以儿童视角讲述中国故事(以儿童视角讲述中国故事)
热门推荐
- css弹性布局设置每行显示指定个数(CSS实现多行多列的布局的实例代码)
- docker 容器相关问题(docker空间爆满导致的进入容器失败的解决方案)
- docker 镜像mysql(解决docker拉取mysql镜像太慢的情况)
- 阿里云oss内网流量(阿里云OSS访问权限配置RAM权限控制实现)
- sql常见的聚合函数有哪些(SQL中的开窗函数详解可代替聚合函数使用)
- python2.7连接sqlserver数据库(Python使用sqlalchemy模块连接数据库操作示例)
- 云服务器怎么设置端口(云服务器80端口是什么意思?)
- C#预处理器指令
- vue表单上传图片数据(vue-cropper插件实现图片截取上传组件封装)
- CSS中 z-index 的用法
排行榜
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9