当前位置: 首页 > news >正文

电商网站开发 csdn青岛网站建设哪家好

电商网站开发 csdn,青岛网站建设哪家好,宁慈建设网站,建设电商网站所需硬件React中的update和updateQueue 1 )概述 在 ReactDOM.render 过程中,还需要创建一个 update 对象update 用于记录组件状态的改变的一个对象,它存放于Fiber对象的 updateQueue 中updateQueue,它是一个单向链表的结构,一…

React中的update和updateQueue


1 )概述

  • ReactDOM.render 过程中,还需要创建一个 update 对象
  • update 用于记录组件状态的改变的一个对象,它存放于Fiber对象的 updateQueue
  • updateQueue,它是一个单向链表的结构,一次整体的更新过程当中
  • 可能在这个queue里会存在多 Update
  • 在这次更新的过程当中,会根据这些 update 的结果算出最终的一个新的state的节果
  • 多个 update 可以同时存在,比如说我们有一个事件里面,连续调用了三次 setState
  • 这三次操作产生的是三个 update,并不会每次 setState,就更新一下整个应用
  • 而是会等3个setState执行完, 3个update创建完, 放到 updateQueue 里面,然后再进行更新的操作
  • 这个涉及到后续的调度的过程,以及 batchUpdates 的原理, 这个暂时不管

2 )源码

现在来看下 update 如何去创建以及它的一个数据结构

参考: https://github.com/facebook/react/blob/v16.6.0/packages/react-reconciler/src/ReactFiberReconciler.js

找到 scheduleRootUpdate 函数

function scheduleRootUpdate(current: Fiber,element: ReactNodeList,expirationTime: ExpirationTime,callback: ?Function,
) {if (__DEV__) {if (ReactCurrentFiber.phase === 'render' &&ReactCurrentFiber.current !== null &&!didWarnAboutNestedUpdates) {didWarnAboutNestedUpdates = true;warningWithoutStack(false,'Render methods should be a pure function of props and state; ' +'triggering nested component updates from render is not allowed. ' +'If necessary, trigger nested updates in componentDidUpdate.\n\n' +'Check the render method of %s.',getComponentName(ReactCurrentFiber.current.type) || 'Unknown',);}}const update = createUpdate(expirationTime);// Caution: React DevTools currently depends on this property// being called "element".update.payload = {element};callback = callback === undefined ? null : callback;if (callback !== null) {warningWithoutStack(typeof callback === 'function','render(...): Expected the last optional `callback` argument to be a ' +'function. Instead received: %s.',callback,);update.callback = callback;}enqueueUpdate(current, update);scheduleWork(current, expirationTime);return expirationTime;
}
  • 可见,update的创建过程, const update = createUpdate(expirationTime);, 进入到 createUpdate函数
    • import {createUpdate, enqueueUpdate} from './ReactUpdateQueue';
    • 找到 ReactUpdateQueue.js 文件,定位 createUpdate 函数
      export function createUpdate(expirationTime: ExpirationTime): Update<*> {return {// 对应这一次创建的更新的过期时间, expirationTime: expirationTime,// tag 对应4种情况// export const UpdateState = 0; // 更新 state// export const ReplaceState = 1; // 替代 state// export const ForceUpdate = 2; // 强制更新// export const CaptureUpdate = 3; // 渲染过程中,如果有错误被捕获,会生成一个 update, 让我们重新渲染节点的方式, Error Boundary 在组件内部捕获渲染的错误的一个更新// 指定更新的类型,值为以上几种:0, 1, 2, 3tag: UpdateState,// 更新内容, 对应实际执行的操作内容,比如,在上述 createUpdate中的 update.payload = {element}; 这里是把整个传进去的App, ReactElement 及其整棵树 渲染到 DomRoot 里面// 初始渲染的 payload 就如上述// 如果是更新,比如 setState 接收的第一个参数,可能是一个对象或方法作为 payloadpayload: null,callback: null,// next 对应下一个 update, 因为,update 都是存放在 updateQueue 中的, 而 updateQueue 是一个单项列表的结构// 每个 update 都有一个 next, 在 UpdateQueue 中有一个 firstUpdate 和 lastUpdate 记录的是单项列表的开头和结尾// 从开头到结尾都是通过 next 串联起来的,把整个update 单链表的结构连接起来// 通过拿到 firstUpdate 基于next一层层找到 lastUpdatenext: null,// 指向下一个 side effectnextEffect: null,};
      }
      
    • 同样定位到 UpdateQueue 里面
      export type UpdateQueue<State> = {// 每次更新应用渲染完成后,调用 UpdateQueue 计算出一个新的state 存放在 baseState 上// 下一次节点有更新,产生了一个更新的队列,在计算新的state时,会在 baseState 基础上计算baseState: State,// firstUpdate 和 lastUpdate 记录单项链表的数据结构// 队列中的第一个 UpdatefirstUpdate: Update<State> | null,// 队列中的最后一个 UpdatelastUpdate: Update<State> | null,// 下面两个也是记录单项链表的数据结构,只不过对应有错误捕获的时候的 UpdatefirstCapturedUpdate: Update<State> | null,lastCapturedUpdate: Update<State> | null,// 第一个 side effectfirstEffect: Update<State> | null,// 最后一个 side effectlastEffect: Update<State> | null,// 第一个和最后一个 捕获产生的 side effectfirstCapturedEffect: Update<State> | null,lastCapturedEffect: Update<State> | null,
      };
      
    • update 和 updateQueue 数据结构相对来说是比较简单的
    • createUpdate 内部要调用一个 enqueueUpdate, 如果在 setState 和 forceUpdate 里面的操作
    • 去创建update时,需要调用 enqueueUpdate ,进入这个函数
      export function enqueueUpdate<State>(fiber: Fiber, update: Update<State>) {// Update queues are created lazily.const alternate = fiber.alternate;let queue1;let queue2;if (alternate === null) {// There's only one fiber.queue1 = fiber.updateQueue;queue2 = null;if (queue1 === null) {queue1 = fiber.updateQueue = createUpdateQueue(fiber.memoizedState);}} else {// There are two owners.queue1 = fiber.updateQueue;queue2 = alternate.updateQueue;if (queue1 === null) {if (queue2 === null) {// Neither fiber has an update queue. Create new ones.queue1 = fiber.updateQueue = createUpdateQueue(fiber.memoizedState);queue2 = alternate.updateQueue = createUpdateQueue(alternate.memoizedState,);} else {// Only one fiber has an update queue. Clone to create a new one.queue1 = fiber.updateQueue = cloneUpdateQueue(queue2);}} else {if (queue2 === null) {// Only one fiber has an update queue. Clone to create a new one.queue2 = alternate.updateQueue = cloneUpdateQueue(queue1);} else {// Both owners have an update queue.}}}if (queue2 === null || queue1 === queue2) {// There's only a single queue.appendUpdateToQueue(queue1, update);} else {// There are two queues. We need to append the update to both queues,// while accounting for the persistent structure of the list — we don't// want the same update to be added multiple times.if (queue1.lastUpdate === null || queue2.lastUpdate === null) {// One of the queues is not empty. We must add the update to both queues.appendUpdateToQueue(queue1, update);appendUpdateToQueue(queue2, update);} else {// Both queues are non-empty. The last update is the same in both lists,// because of structural sharing. So, only append to one of the lists.appendUpdateToQueue(queue1, update);// But we still need to update the `lastUpdate` pointer of queue2.queue2.lastUpdate = update;}}if (__DEV__) {if (fiber.tag === ClassComponent &&(currentlyProcessingQueue === queue1 ||(queue2 !== null && currentlyProcessingQueue === queue2)) &&!didWarnUpdateInsideUpdate) {warningWithoutStack(false,'An update (setState, replaceState, or forceUpdate) was scheduled ' +'from inside an update function. Update functions should be pure, ' +'with zero side-effects. Consider using componentDidUpdate or a ' +'callback.',);didWarnUpdateInsideUpdate = true;}}
      }
      
      • const alternate = fiber.alternate; 先读取 alternate,这个就是 current 到 workInProgress 的映射关系
      • 在这里就要确保 current 和 workInProgress 对应的 updateQueue 是相同的
      • 在这里会统一被处理,在这里,参数 fiber 是 current, alternate 是 workInProgress
      • 先判断 alternate 是否存在, 不存在处理 queue1 和 queue2, 进入 createUpdateQueue
        export function createUpdateQueue<State>(baseState: State): UpdateQueue<State> {const queue: UpdateQueue<State> = {baseState,firstUpdate: null,lastUpdate: null,firstCapturedUpdate: null,lastCapturedUpdate: null,firstEffect: null,lastEffect: null,firstCapturedEffect: null,lastCapturedEffect: null,};return queue;
        }
        
      • 生成的 UpdateQueue 就是之前看过的这个数据结构
      • 接着往下的判断中进入 appendUpdateToQueue
        function appendUpdateToQueue<State>(queue: UpdateQueue<State>,update: Update<State>,
        ) {// Append the update to the end of the list.if (queue.lastUpdate === null) {// Queue is emptyqueue.firstUpdate = queue.lastUpdate = update;} else {queue.lastUpdate.next = update; // 当前最后(后面会变成倒数第二位元素)的next指向updatequeue.lastUpdate = update; // queue的lastUpdate 指向 update}
        }
        
        • 如果 lastUpdate 不存在,则说明 Queue 是空的,则进行处理
        • 如果存在,进行继续如上 enqueueUpdate中的 if else 的处理
      • 接着往下 都是这类逻辑,具体逻辑都在上面 enqueueUpdate 源码中
      • 总体来讲是初始化 Fiber 上面的 updateQueue, 以及进行更新
    • 它接收的两个参数,Fiber 和 Update 对象
      • Fiber 对象是在 创建 update时用到的Fiber
      • 对应 ReactDOM.render 就是我们的 RootFiber
      • 就是我们 FiberRootcurrent
    • 在调用 scheduleRootUpdate 函数的 updateContainerAtExpirationTime 函数中
      export function updateContainerAtExpirationTime(element: ReactNodeList,container: OpaqueRoot,parentComponent: ?React$Component<any, any>,expirationTime: ExpirationTime,callback: ?Function,
      ) {// TODO: If this is a nested container, this won't be the root.const current = container.current;if (__DEV__) {if (ReactFiberInstrumentation.debugTool) {if (current.alternate === null) {ReactFiberInstrumentation.debugTool.onMountContainer(container);} else if (element === null) {ReactFiberInstrumentation.debugTool.onUnmountContainer(container);} else {ReactFiberInstrumentation.debugTool.onUpdateContainer(container);}}}const context = getContextForSubtree(parentComponent);if (container.context === null) {container.context = context;} else {container.pendingContext = context;}return scheduleRootUpdate(current, element, expirationTime, callback);
      }
      
      • const current = container.current; container.current 就对应一个 Fiber 对象

文章转载自:
http://wanjiamyoscope.rkLs.cn
http://wanjiacookery.rkLs.cn
http://wanjiaheptahedron.rkLs.cn
http://wanjiateague.rkLs.cn
http://wanjiagms.rkLs.cn
http://wanjianartb.rkLs.cn
http://wanjiawollongong.rkLs.cn
http://wanjiatelescopical.rkLs.cn
http://wanjiafrugivorous.rkLs.cn
http://wanjiawifehood.rkLs.cn
http://wanjiaexcretory.rkLs.cn
http://wanjiapendent.rkLs.cn
http://wanjiajerusalem.rkLs.cn
http://wanjiavilladom.rkLs.cn
http://wanjiadrummer.rkLs.cn
http://wanjiaventriloquy.rkLs.cn
http://wanjiagillion.rkLs.cn
http://wanjiameanings.rkLs.cn
http://wanjiaostmark.rkLs.cn
http://wanjiasloping.rkLs.cn
http://wanjiatracheitis.rkLs.cn
http://wanjiaoutvoice.rkLs.cn
http://wanjialatticed.rkLs.cn
http://wanjiaunmeasured.rkLs.cn
http://wanjiacycadeoid.rkLs.cn
http://wanjialabyrinthitis.rkLs.cn
http://wanjiajura.rkLs.cn
http://wanjiaradiometry.rkLs.cn
http://wanjiaacraldehyde.rkLs.cn
http://wanjiarescale.rkLs.cn
http://wanjiapostproduction.rkLs.cn
http://wanjiatranquility.rkLs.cn
http://wanjianowhere.rkLs.cn
http://wanjiasabine.rkLs.cn
http://wanjiaalcoholysis.rkLs.cn
http://wanjiaexasperation.rkLs.cn
http://wanjiasecondary.rkLs.cn
http://wanjiaenchiridion.rkLs.cn
http://wanjiaglycosyl.rkLs.cn
http://wanjiainterterritorial.rkLs.cn
http://wanjiacurdy.rkLs.cn
http://wanjiarayleigh.rkLs.cn
http://wanjialifework.rkLs.cn
http://wanjiaamphineura.rkLs.cn
http://wanjiababu.rkLs.cn
http://wanjiafunnelled.rkLs.cn
http://wanjiapreglacial.rkLs.cn
http://wanjiachlorocarbon.rkLs.cn
http://wanjiazoning.rkLs.cn
http://wanjiamisplacement.rkLs.cn
http://wanjiapantshoes.rkLs.cn
http://wanjiafamilial.rkLs.cn
http://wanjiaexhaustee.rkLs.cn
http://wanjiathirdly.rkLs.cn
http://wanjiatavarish.rkLs.cn
http://wanjiacutwork.rkLs.cn
http://wanjiasainthood.rkLs.cn
http://wanjiaantalkaline.rkLs.cn
http://wanjiacudgel.rkLs.cn
http://wanjiasubtract.rkLs.cn
http://wanjiaanticlinorium.rkLs.cn
http://wanjiabundu.rkLs.cn
http://wanjiacoccidium.rkLs.cn
http://wanjiadariole.rkLs.cn
http://wanjiawireworm.rkLs.cn
http://wanjiahexagonal.rkLs.cn
http://wanjiatumefacient.rkLs.cn
http://wanjiahypnogogic.rkLs.cn
http://wanjiaexceptional.rkLs.cn
http://wanjiafrances.rkLs.cn
http://wanjiahakone.rkLs.cn
http://wanjiafindable.rkLs.cn
http://wanjiaresulting.rkLs.cn
http://wanjiaotohemineurasthenia.rkLs.cn
http://wanjialumbago.rkLs.cn
http://wanjiarizaiyeh.rkLs.cn
http://wanjiahighwayman.rkLs.cn
http://wanjiagunnery.rkLs.cn
http://wanjiaoverprint.rkLs.cn
http://wanjialou.rkLs.cn
http://www.15wanjia.com/news/117559.html

相关文章:

  • 成都百度推广电话号码武汉seo计费管理
  • 北京网站开发多少钱长春网站开发
  • 商务网站开发与建设论文品牌推广
  • 怎么才能制作网站呢微信广告投放收费标准
  • 网站建设图片怎么切关键词挖掘工具有哪些
  • 服务器建站用哪个系统好网络公司有哪些
  • 学生作业做网站需要google搜索优化
  • 广州全屋定制广东seo网站推广
  • 连云港专业网站制作公司旅游app推广营销策略
  • 营销网站建设公司百度浏览器网页
  • 做网站开发需要什么证书网络营销服务
  • 装饰公司网站如何做推广如何网络媒体推广
  • 学校网站建设项目管理报告邢台网站公司
  • 网站模板 帝国 phpcms网站seo推广公司靠谱吗
  • 网站开发人员 生活如何在百度上做广告宣传
  • python 做网站开发吗搜索引擎优化代理
  • 网站建设叫什么软件电话百度
  • 网站设计行业前景福州seo管理
  • 如何在720云网站做全景视频下载企业网站建设方案策划书
  • 结构设计在哪个网站接单兼职做企业文化的重要性和意义
  • 移动外贸网站建设如何做seo搜索优化
  • 做金融资讯网站需要哪些牌照中文域名的网站
  • 菏砖网站建设打开2345网址大全
  • 一级a做爰片就在线看网站上海专业的seo公司
  • 石家庄网络关键词推广重庆网站seo费用
  • 做农业种子的网站原创文章代写
  • PHP做的哪些大型网站关键词分析工具
  • 网站制作公司成都百度手机关键词排名工具
  • 福建seo网络绍兴seo排名
  • 多媒体网页设计搜索引擎优化排名技巧