React中的优先级

React源码分析8-状态更新的优先级机制 react的优先级机制在源码中并不是一个独立的,解耦的模块,而是涉及到了react整体运行的方方面面,最后回归整理下优先级机制在源码中的使用,让大家对优先级机制有一个更加整体的认知。时间分片。涉及到任务打断、根据优先级计算分片时长setState 生成 Update 对象。每个 Update 对象里面都有一个 lane 属性,代表此次更新的优先级高优先级任务打断低优先级任务。每一次调度都会对正在进行任务和当前任务最高优先级做比较,如果不相等,就代表有高优先级任务进来,需要打断当前正在的任务。 阅读详情

为什么React需要优先级?

vue和react有一个很大的区别就是他们的渲染方式的不同,Vue可以更快地计算出Virtual DOM的差异,这是由于它在渲染过程中,会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树。另外Vue3还进行了diff算法的静态标记, 静态提升
React在应用的状态被改变时,全部子组件都会重新渲染。虽然也可以通过开发人员手动的对一些依赖进行处理优化渲染, 但是真实的开发中, 很少会有人去那么做, 所以这也是为什么react需要更多的算法, 优先级, 时间切片等方式去优化性能

React中的优先级

 UI产生交互的根本原因是各种事件,这也就意味着事件与更新有着直接关系。不同事件产生的更新,它们的优先级是有差异的,所以更新优先级的根源在于事件的优先级。一个更新的产生可直接导致React生成一个更新任务,最终这个任务被Scheduler调度。

所以在React中,人为地将事件划分了等级,最终目的是决定调度任务的轻重缓急,因此,React有一套从事件到调度的优先级机制。

本文将围绕事件优先级、更新优先级、任务优先级、调度优先级,重点梳理它们之间的转化关系。

  •  事件优先级:按照用户事件的交互紧急程度,划分的优先级
  •  更新优先级:事件导致React产生的更新对象(update)的优先级(update.lane)
  •  任务优先级:产生更新对象之后,React去执行一个更新任务,这个任务所持有的优先级
  •  调度优先级:Scheduler依据React更新任务生成一个调度任务,这个调度任务所持有的优先级

前三者属于React的优先级机制,第四个属于Scheduler的优先级机制,Scheduler内部有自己的优先级机制,虽然与React有所区别,但等级的划分基本一致。下面我们从事件优先级开始说起。

优先级的起点:事件优先级

React按照事件的紧急程度,把它们划分成三个等级:

  •  离散事件(DiscreteEvent):click、keydown、focusin等,这些事件的触发不是连续的,优先级为0。
  •  用户阻塞事件(UserBlockingEvent):drag、scroll、mouseover等,特点是连续触发,阻塞渲染,优先级为1。
  •  连续事件(ContinuousEvent):canplay、error、audio标签的timeupdate和canplay,优先级最高,为2。

派发事件优先级

事件优先级是在注册阶段被确定的,在向root上注册事件时,会根据事件的类别,创建不同优先级的事件监听(listener),最终将它绑定到root上去。 

let listener = createEventListenerWrapperWithPriority(  
    targetContainer,  
    domEventName,  
    eventSystemFlags,  
    listenerPriority,  
  ); 

createEventListenerWrapperWithPriority函数的名字已经把它做的事情交代得八九不离十了。它会首先根据事件的名称去找对应的事件优先级,然后依据优先级返回不同的事件监听函数。 

export function createEventListenerWrapperWithPriority(  
  targetContainer: EventTarget,  
  domEventName: DOMEventName,  
  eventSystemFlags: EventSystemFlags,  
  priority?: EventPriority, 
): Function {  
  const eventPriority =  
    priority === undefined  
      ? getEventPriorityForPluginSystem(domEventName)  
      : priority;  
  let listenerWrapper;  
  switch (eventPriority) {  
    case DiscreteEvent:  
      listenerWrapper = dispatchDiscreteEvent;  
      break;  
    case UserBlockingEvent:  
      listenerWrapper = dispatchUserBlockingUpdate;  
      break;  
    case ContinuousEvent:  
    default:  
      listenerWrapper = dispatchEvent;  
      break;  
  }  
  return listenerWrapper.bind(  
    null,  
    domEventName,  
    eventSystemFlags,  
    targetContainer,  
  );  
} 

最终绑定到root上的事件监听其实是dispatchDiscreteEvent、dispatchUserBlockingUpdate、dispatchEvent这三个中的一个。它们做的事情都是一样的,以各自的事件优先级去执行真正的事件处理函数。

比如:dispatchDiscreteEvent和dispatchUserBlockingUpdate最终都会以UserBlockingEvent的事件级别去执行事件处理函数。

以某种优先级去执行事件处理函数其实要借助Scheduler中提供的runWithPriority函数来实现: 

function dispatchUserBlockingUpdate(  
  domEventName,  
  eventSystemFlags,  
  container,  
  nativeEvent,  
) {  
  ...  
  runWithPriority(  
    UserBlockingPriority,  
    dispatchEvent.bind(  
      null,  
      domEventName,  
      eventSystemFlags,  
      container,  
      nativeEvent,  
    ),  
  );  
  ...  
} 

这么做可以将事件优先级记录到Scheduler中,相当于告诉Scheduler:你帮我记录一下当前事件派发的优先级,等React那边创建更新对象(即update)计算更新优先级时直接从你这拿就好了。 

function unstable_runWithPriority(priorityLevel, eventHandler) {  
  switch (priorityLevel) {  
    case ImmediatePriority:  
    case UserBlockingPriority:  
    case NormalPriority: 
     case LowPriority:  
    case IdlePriority:  
      break;  
    default:  
      priorityLevel = NormalPriority;  
  }  
  var previousPriorityLevel = currentPriorityLevel;  
  // 记录优先级到Scheduler内部的变量里  
  currentPriorityLevel = priorityLevel;  
  try {  
    return eventHandler();  
  } finally {  
    currentPriorityLevel = previousPriorityLevel;  
  }  
} 

更新优先级

以setState为例,事件的执行会导致setState执行,而setState本质上是调用enqueueSetState,生成一个update对象,这时候会计算它的更新优先级,即update.lane: 

const classComponentUpdater = {  
  enqueueSetState(inst, payload, callback) {  
    ...  
    // 依据事件优先级创建update的优先级  
    const lane = requestUpdateLane(fiber, suspenseConfig);  
    const update = createUpdate(eventTime, lane, suspenseConfig);  
    update.payload = payload;  
    enqueueUpdate(fiber, update);  
    // 开始调度  
    scheduleUpdateOnFiber(fiber, lane, eventTime);  
    ...  
  },  
}; 

重点关注requestUpdateLane,它首先找出Scheduler中记录的优先级:schedulerPriority,然后计算更新优先级:lane,具体的计算过程在findUpdateLane函数中,计算过程是一个从高到低依次占用空闲位的操作,具体的代码在这里 ,这里就先不详细展开。 

export function requestUpdateLane(  
  fiber: Fiber,  
  suspenseConfig: SuspenseConfig | null,  
): Lane {  
  ...  
  // 根据记录下的事件优先级,获取任务调度优先级  
  const schedulerPriority = getCurrentPriorityLevel();  
  let lane;  
  if (  
    (executionContext & DiscreteEventContext) !== NoContext &&  
    schedulerPriority === UserBlockingSchedulerPriority  
  ) {  
    // 如果事件优先级是用户阻塞级别,则直接用InputDiscreteLanePriority去计算更新优先级  
    lane = findUpdateLane(InputDiscreteLanePriority, currentEventWipLanes);  
  } else {  
    // 依据事件的优先级去计算schedulerLanePriority  
    const schedulerLanePriority = schedulerPriorityToLanePriority(  
      schedulerPriority,  
    );  
    ...  
    // 根据事件优先级计算得来的schedulerLanePriority,去计算更新优先级  
    lane = findUpdateLane(schedulerLanePriority, currentEventWipLanes);  
  }  
  return lane;  
} 

getCurrentPriorityLevel负责读取记录在Scheduler中的优先级: 

function unstable_getCurrentPriorityLevel() {  
  return currentPriorityLevel;  
} 

update对象创建完成后意味着需要对页面进行更新,会调用scheduleUpdateOnFiber进入调度,而真正开始调度之前会计算本次产生的更新任务的任务优先级,目的是与已有任务的任务优先级去做比较,便于做出多任务的调度决策。

调度决策的逻辑在ensureRootIsScheduled 函数中,这是一个非常重要的函数,控制着React任务进入Scheduler的大门。

任务优先级

一个update会被一个React的更新任务执行掉,任务优先级被用来区分多个更新任务的紧急程度,它由更新优先级计算而来,举例来说:

假设产生一前一后两个update,它们持有各自的更新优先级,也会被各自的更新任务执行。经过优先级计算,如果后者的任务优先级高于前者的任务优先级,那么会让Scheduler取消前者的任务调度;如果后者的任务优先级等于前者的任务优先级,后者不会导致前者被取消,而是会复用前者的更新任务,将两个同等优先级的更新收敛到一次任务中;如果后者的任务优先级低于前者的任务优先级,同样不会导致前者的任务被取消,而是在前者更新完成后,再次用Scheduler对后者发起一次任务调度。

这是任务优先级存在的意义,保证高优先级任务及时响应,收敛同等优先级的任务调度。

任务优先级在即将调度的时候去计算,代码在ensureRootIsScheduled函数中: 

function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {  
  ...  
  // 获取nextLanes,顺便计算任务优先级  
  const nextLanes = getNextLanes(  
    root,  
    root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes,  
  );  
  // 获取上面计算得出的任务优先级  
  const newCallbackPriority = returnNextLanesPriority();  
  ...  
} 

通过调用getNextLanes去计算在本次更新中应该处理的这批lanes(nextLanes),getNextLanes会调用getHighestPriorityLanes去计算任务优先级。任务优先级计算的原理是这样:更新优先级(update的lane),它会被并入root.pendingLanes,root.pendingLanes经过getNextLanes处理后,挑出那些应该处理的lanes,传入getHighestPriorityLanes,根据nextLanes找出这些lanes的优先级作为任务优先级。 

复制
function getHighestPriorityLanes(lanes: Lanes | Lane): Lanes {  ...  
  // 都是这种比较赋值的过程,这里只保留两个以做简要说明  
  const inputDiscreteLanes = InputDiscreteLanes & lanes;  
  if (inputDiscreteLanes !== NoLanes) {  
    return_highestLanePriority = InputDiscreteLanePriority;  
    return inputDiscreteLanes;  
  }  
  if ((lanes & InputContinuousHydrationLane) !== NoLanes) { 
    return_highestLanePriority = InputContinuousHydrationLanePriority;  
    return InputContinuousHydrationLane;  
  }  
  ...  
  return lanes;  
} 

getHighestPriorityLanes的源码在这里,getNextLanes的源码在这里

return_highestLanePriority就是任务优先级,它有如下这些值,值越大,优先级越高,暂时只理解任务优先级的作用即可。 

复制
export const SyncLanePriority: LanePriority = 17;  
export const SyncBatchedLanePriority: LanePriority = 16;  
const InputDiscreteHydrationLanePriority: LanePriority = 15;  
export const InputDiscreteLanePriority: LanePriority = 14;  
const InputContinuousHydrationLanePriority: LanePriority = 13;  
export const InputContinuousLanePriority: LanePriority = 12;  
const DefaultHydrationLanePriority: LanePriority = 11;  
export const DefaultLanePriority: LanePriority = 10;  
const TransitionShortHydrationLanePriority: LanePriority = 9;  
export const TransitionShortLanePriority: LanePriority = 8;  
const TransitionLongHydrationLanePriority: LanePriority = 7;  
export const TransitionLongLanePriority: LanePriority = 6;  
const RetryLanePriority: LanePriority = 5;  
const SelectiveHydrationLanePriority: LanePriority = 4;  
const IdleHydrationLanePriority: LanePriority = 3;  
const IdleLanePriority: LanePriority = 2;  
const OffscreenLanePriority: LanePriority = 1;  
export const NoLanePriority: LanePriority = 0; 

如果已经存在一个更新任务,ensureRootIsScheduled会在获取到新任务的任务优先级之后,去和旧任务的任务优先级去比较,从而做出是否需要重新发起调度的决定,若需要发起调度,那么会去计算调度优先级。

调度优先级

一旦任务被调度,那么它就会进入Scheduler,在Scheduler中,这个任务会被包装一下,生成一个属于Scheduler自己的task,这个task持有的优先级就是调度优先级。

它有什么作用呢?在Scheduler中,分别用过期任务队列和未过期任务的队列去管理它内部的task,过期任务的队列中的task根据过期时间去排序,最早过期的排在前面,便于被最先处理。而过期时间是由调度优先级计算得出的,不同的调度优先级对应的过期时间不同。

调度优先级由任务优先级计算得出,在ensureRootIsScheduled更新真正让Scheduler发起调度的时候,会去计算调度优先级。 

复制
function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {  
    ...  
    // 根据任务优先级获取Scheduler的调度优先级  
    const schedulerPriorityLevel = lanePriorityToSchedulerPriority(  
      newCallbackPriority,  
    );  
    // 计算出调度优先级之后,开始让Scheduler调度React的更新任务  
    newCallbackNode = scheduleCallback(  
      schedulerPriorityLevel,  
      performConcurrentWorkOnRoot.bind(null, root),  
    );  
    ... 
} 

lanePriorityToSchedulerPriority计算调度优先级的过程是根据任务优先级找出对应的调度优先级。 

复制
export function lanePriorityToSchedulerPriority(  
  lanePriority: LanePriority,  
): ReactPriorityLevel {  
  switch (lanePriority) {  
    case SyncLanePriority:  
    case SyncBatchedLanePriority:  
      return ImmediateSchedulerPriority;  
    case InputDiscreteHydrationLanePriority:  
    case InputDiscreteLanePriority:  
    case InputContinuousHydrationLanePriority:  
    case InputContinuousLanePriority:  
      return UserBlockingSchedulerPriority;  
    case DefaultHydrationLanePriority:  
    case DefaultLanePriority:  
    case TransitionShortHydrationLanePriority:  
    case TransitionShortLanePriority:  
    case TransitionLongHydrationLanePriority:  
    case TransitionLongLanePriority:  
    case SelectiveHydrationLanePriority:  
    case RetryLanePriority:  
      return NormalSchedulerPriority;  
    case IdleHydrationLanePriority:  
    case IdleLanePriority: 
    case OffscreenLanePriority:  
      return IdleSchedulerPriority;  
    case NoLanePriority:  
      return NoSchedulerPriority;  
    default:  
      invariant(  
        false,  
        'Invalid update priority: %s. This is a bug in React.',  
        lanePriority, 
       );  
  }  
} 

总结

本文一共提到了4种优先级:事件优先级、更新优先级、任务优先级、调度优先级,它们之间是递进的关系。事件优先级由事件本身决定,更新优先级由事件计算得出,然后放到root.pendingLanes,任务优先级来自root.pendingLanes中最紧急的那些lanes对应的优先级,调度优先级根据任务优先级获取。几种优先级环环相扣,保证了高优任务的优先执行。 

React源码分析7-state计算流程和优先级 看到上面的原理解析是不是很复杂,我们可以忽略所有的实现细节,回归现象本质,state计算就是遍历 update对象 链表根据 payload 得到新的state。在此前提下,因为优先级机制,打断之后会还原节点,从而会引起 update对象 丢失问题 和 state计算连续性问题。解决这两个问题才是我们上面说的复杂的实现细节看到上面的原理解析是不是很复杂,我们可以忽略所有的实现细节,回归现象本质,state计算就是遍历 update对象 链表根据 payload 得到新的state。 阅读详情

相关推荐

【React】“车道”模型 - 区分优先级

在今天的场景中,比起 “优先级” ,有个更适合的词或者理念,叫做 “车道模型”。在 React 内部使用了 Lane 这个单词,相信这篇文章可以让大家不仅停留在这个单词的直译上,而是真的理解 “车道模型”。 整体流程 我们先从整体上看一下,从 “数据变更” 到 “渲染” 的链路是怎样的: 当我们更改数据时,其实是创建了一个更新 **Update** 。这个 **Update** 上会有一个属性 **lane** ,用来标记该更新所属的 “车道” 。 接着这个 **Update** 会被添加到对应 Fibe

郊眠寺 794

React18源码: React调度中的3种优先级类型和Lane的位运算

可以看得出来lane&-lane的结果是SyncLane,所以通过lane&-lane就能分离出最高优先级的任务。即A(cpu)>B(IO)>C(cpu).此时的需求需要将任务B从group中分离出来,先处理cpu任务A和C。在新版本的React中,还有一个新特性,就是render阶段可能被中断,在这个期间会产生一个更高优先级的任务。如上就是通过 lanes & -lanes 分离出最高优先级的任务的,我们来看一下具体的流程。也即是说lane的代表的数值越小,此次更新的优先级就越大。

Wang的专栏 2393

React中的高优先级任务插队机制

在React的concurrent模式下,低优先级任务执行过程中,一旦有更高优先级的任务进来,那么这个低优先级的任务会被取消,优先执行高优先级任务。等高优先级任务做完了,低优先级任务会被重新做一遍。 我们用一个具体的例子来理解一下高优先级任务插队。 有这样一个组件,state为0,进入页面,会调用setState将state加1,这个作为低优先级任务。React开始进行更新,在这个低优先级任务尚未完成时,模拟按钮点击,state加2,这个作为高优先级任务。可以看到,页面上的数字变化为0 -> 2

与其临渊羡鱼,不如退而结网 1425

【React源码】(六)React 中的优先级管理

本文介绍了 react 源码中有关优先级的部分, 并梳理了 3 种优先级之间的区别和联系. 它们贯穿了reconciler 运作流程中的 4 个阶段, 在 react 源码中所占用的代码量比较高, 理解它们的设计思路, 为接下来分析调度原理和fiber构造打下基础.

weixin_44828588的博客 1062

Pylon SDK C语言多相机采集的注意事项、关键设置及代码示例

前言 与单相机直接用句柄PYLON_DEVICE_HANDLE hdev进行操作所不同的是,在多相机连接采用索引值访问每个相机,对应句柄为PYLON_DEVICE_HANDLE hdev[deviceIndex] 。若连接N个相机设备,则索引值范围为[0,...,N-1]。显而易见,采用循环结构编程可以对多个相机采用同样的操作,包括参数设置、图像采集等。但多个相机的使用需要根据相机功能、相机与主机间的连接方式、网络适配器进行额外的设置。本文参考Pylon C开发者手册和Basler产品文档,对GigE类型

黑化咸鱼的博客 3089

Flexible H-Tree(灵活 H 树)与 Multi-Tap 时钟流程解析

通过灵活 H 树与多抽头技术的结合,复杂时钟架构可在保持电气对称性的同时适应不规则布局,为高性能、低功耗 SoC 设计提供高效的时钟网络解决方案。

weixin_45371279的博客 1914

一眼就懂的 React 调度算法

react 的调度,采用优先级调度(Priority),代码量大且复杂,看了下 fre 中的调度实现(最短剩余时间优先),比较精简且适合快速学习。 问题产生:GUI渲染线程与JS引擎是互斥的,所以需要避免 js 长时间占用导致页面绘制卡顿。 调度核心:频繁发起一个宏任务,根据事件循环机制避免 js 长时间占用(这里需要 fiber 的架构模式)。 代码实现: const queue = [] // react中为 5ms,fre中为16ms 是多少目前看无所谓 const threshold .

susuzhe 918

AudioTrack音频播放流程深度解析

深入解析Android AudioTrack音频播放的完整链路:从Java API到Native层,从共享内存Ring Buffer机制到FAST Track低延迟优化,配合源码分析带你彻底搞懂Android音频播放的底层原理

Cheson的专栏 938

React 优先级队列小顶堆的简单实现

我们都知道 React Schedule 中的优先级队列,本身采用小顶堆来保证队列的第一个任务是优先级最高的,并且获取优先级最高的任务的时间复杂度为 O(1)。但由于小顶堆的特性,我们需要保证第一个任务优先级要最高,所以需要拿新任务和他的所有父节点去进行对比。移除操作也是同理,移除一个高优先级任务之后,会把队尾的任务提高最顶部来,为了保证小顶堆的特性,所以需要拿这个任务和其子节点进行对比。首先优先级队列有两种操作,一种是添加任务,另外一种是移除优先级最高的任务(第一个任务)

WF帆少的博客 803

GD32F4x芯片加密实战:从读保护到安全启动全解析

本文详细解析了GD32F4x芯片加密的实战操作,从读保护功能到安全启动全流程。通过具体代码示例和应用场景分析,帮助开发者有效防止固件被盗用,提升工业控制、智能门锁等场景下的数据安全性。重点介绍了读保护功能的底层机制、配置步骤及常见问题解决方案。

weixin_42629671的博客 207

YOLO26涨点改进 | 细节涨点篇 | 源自SCI一区 | YOLO26引入HWD小波下采样模块,而不会显著增加计算开销,(适合小目标分割任务、小目标检测任务)

本文提出了一种基于Haar小波变换的下采样模块HWD,用于改进YOLO26目标检测性能。HWD模块通过小波变换降低特征图分辨率,同时将空间信息编码到通道维度,有效保留了关键信息。相比传统下采样方法,HWD能显著减少信息不确定性,提升小目标检测精度。实验表明,该模块可无缝集成到CNN架构中,不增加计算开销。文章详细介绍了HWD的实现原理、代码结构以及在YOLO26中的集成方法,并提供了两种改进版yaml配置文件。该创新模块已在多种数据集上验证有效,特别适合语义分割和目标检测任务。

Ai缝合怪、助力小伙伴高效发论文 401

React 第三十四章 React 渲染流程

注意上面 render 阶段的工作是在内存里面进行的,不会更新宿主环境 UI,因此这个阶段即使工作流程反复被中断,用户也不会看到“更新不完整的UI”。当 Scheduler 调度完成后,将任务交给 Reconciler,Reconciler 就需要计算出新的 UI,最后就由 Renderer进行渲染更新操作。

aXin_li的博客 1980

Python全栈入门到实战【基础篇 05】核心基础:Python的2种运行模式(交互式+命令行式)

Python代码运行模式详解:交互式与命令行式对比 摘要: Python提供两种核心运行模式:交互式(REPL)和命令行式(脚本式)。交互式模式适合快速测试语法,即时反馈结果,通过终端输入python启动,特点是无需保存、临时执行,适合验证小段代码逻辑。命令行式模式需将代码保存为.py文件后运行,适合开发完整程序,可重复执行和修改。两种模式各有优势:交互式便于学习调试,命令行式适合实际开发。掌握两种模式的使用场景和切换方法,是Python入门的关键技能,能显著提升学习效率。

那些看似不起波澜的日复一日,会在某天让你看到坚持的意义 4553

React中的4种优先级

来源 |http://www.fly63.com/article/detial/10072UI产生交互的根本原因是各种事件,这也就意味着事件与更新有着直接关系。不同事件产生的更新,它们...

web前端开发 2542

java技术专家【面试】Java程序员英语面试整个流程

java技术专家【面试】Java程序员英语面试整个流程

大壮 751

物联网Node-Red开发教程-第6章 HTTP与Web服务

本章摘要(147字): 本章系统讲解了Node-RED中的HTTP节点应用,重点包括: 三大核心HTTP节点功能:http in(接收请求)、http response(返回响应)、http request(调用外部API) 详细演示了REST API开发流程,包括路径参数(req.params)处理和响应构造 提供了创建Hello World API、传感器数据接口等实用示例 涵盖HTTP方法特性、状态码设置及响应头配置等关键知识点 通过流程图和JSON配置直观展示节点连接方式,帮助快速掌握Web服务开发

shihui2003的博客 264

React 状态更新中的双缓冲机制、优先级调度

react 的状态更新机制

Jacoh的专栏 699

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

React18源码: Fiber树中的优先级与帧栈模型

针对fiber对象或update对象,只要它们的优先级(如:fiber.lanes和update.lane)比渲染优先级低,都将会被忽略。在前文 double buffering 中分析过,HostRootFiber.alternate 是正在构造的fiber树的根节点。可以看到,无论是应用初始化或者发起组件更新,创建update.lane的逻辑都是一样的。此处返回的lanes会作为全局渲染的优先级,用于fiber树构造过程中。所以每次fiber树构造是一个独立的过程,需要独立的一组全局变量。

Wang的专栏 1324

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

React 并发渲染的性能剖析:Fiber 架构中的优先级调度与时间切片机制

React 并发渲染的核心是"让更紧急的事情先做"。Fiber 的时间切片机制允许 React 在渲染过程中暂停,让出主线程给用户交互;Lane 优先级模型允许开发者声明状态更新的紧急程度(useTransition/useDeferredValue)。实用建议:只在用户交互密集的组件(搜索输入、拖拽、动画)中使用并发特性。先识别"用户操作后响应卡顿"的场景 → 区分"需要立即响应的更新"和"可以延迟的更新"→ 对后者使用 useTransition。

qq_34803115的博客 4761

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

React18源码: React中的LanePriority和SchedulerPriority

reactPriorityLevel, 属于react-reconciler包,定义于 SchedulerWithReactIntegration.js中。与fiber构造过程相关的优先级(如fiber.updateQueue,fiber.lanes)都使用LanePriority.为了能协同调度中心(scheduler 包) 和 fiber树构造(react-reconciler包)中对优先级的使用。由于本节重点介绍优先级体系以及它们的转换关系,关于Lane(车道模型)在fiber树构造时使用。

Wang的专栏 1623

react scheduler调度优先级学习

优先级 并不是所有的state更新都需要立即显示出来,比如屏幕之外的部分的更新 并不是所有的更新优先级都是一样的,比如用户输入的响应优先级要比通过请求填充内容的响应优先级更高 理想情况下,对于某些高优先级的操作,应该是可以打断低优先级的操作执行的,比如用户输入时,页面的某个评论还在reconciliation,应该优先响应用户输入 理想状况下reconciliation的过程应该是每次只做一个很小的任务,做完后能够回到主线程看下有没有什么更高优先级的任务需要处理,如果又则先处理更高优先级的任务,没有则继

weixin_43294560的博客 710

【React源码解析】React更新优先级

这里就回到了上面提到的多更新并存的问题:哪些更新优先级高,哪些更新优先级低,哪些更新需要立即去执行,哪些更新可以缓一缓再执行。搜索时,我们应该确保用户输入的内容是能够是实时响应的,而根据输入值搜索出来的内容在渲染更新的时候不应该阻塞用户的输入。通过这种优先级,我们就能判断哪些更新优先执行,哪些更新会被中断滞后执行了。在更新的时候就会依次去执行这个链表上的操作,从而计算出最终的。对于用户体验来讲,紧急更新应该是优先于非紧急更新的。的更新优先级,属于哪个更新任务中的操作。实际上,在每次更新时,更新。

liangzhenmeng的博客 2万+

React中的调度器是一个独立于React和React DOM的模块,它负责管理和调度任务的执行

它的作用是根据任务的优先级来安排任务的执行顺序,以提高应用程序的性能和响应能力。React中的任务被分为不同的优先级,调度器根据任务的优先级来决定任务的执行顺序。React调度器会根据任务的优先级来决定任务的调度顺序。React中的调度器是一个独立于React和React DOM的模块,它负责管理和调度任务的执行。调度器使用优先级来确定任务的执行顺序,并根据当前的浏览器空闲时间来安排任务的执行。通过这三种类型的管理,React调度器能够根据任务的优先级来合理地调度和执行任务,提高应用的性能和响应速度。

[Blog][Domain] programb.blog.youkuaiyun.com 1088

React16源码: React中ReactFiberScheduler的expirationTime及nextExpirationTimeToWorkOn的源码实现

expirationTime 作用在渲染之前的,而 nextExpirationTimeToWorkOn 则是作用在渲染时的。让它在下一次执行更新之前来使用 performSyncWork 这种方式来通过同步的方式去渲染任务。这两个值在整个 render 以及 commit 的过程当中,都起着非常重要的一个作用。所以这就是这两个值它的作用, 通过指定它们来指定更新模式以及更新任务的优先级。为什么说 expirationTime 是作用在渲染前的呢?比如说, 在 renderRoot 中。

Wang的专栏 1274
上一篇: 如何封装一个自定义错误规则校验
下一篇: Nginx学习(docker部署及常用配置)
MaxLoongLvs
博客等级 码龄9年 226粉丝 170原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值