web前部培训React合成事件原理解析
来源:智能 2024年12月16日 12:16
经过这一系列反复,惨剧国安局缓冲器listener就此被可选到root表达方式上。
// 根据惨剧中文名称,成立多种不同服务缓冲器端的惨剧国安局缓冲器。
let listener = createEventListenerWrapperWithPriority(
targetContainer,
domEventName,
eventSystemFlags,
listenerPriority,
);
// 可选惨剧
if (isCapturePhaseListener) {
unsubscribeListener = addEventCaptureListener(
targetContainer,
domEventName,
listener,
);
} else {
unsubscribeListener = addEventBubbleListener(
targetContainer,
domEventName,
listener,
);
}
惨剧国安局缓冲器listener是谁
请注意所述的可选惨剧的时候,可选到root上的惨剧国安局表达式是listener,然而这个listener并不是我们如此一来在模块当中的写的惨剧妥善处理表达式。通过请注意的示例可知,listener是createEventListenerWrapperWithPriority的codice_结果
为什么要成立这么一个listener,而不是如此一来可选写在模块当中的的惨剧妥善处理表达式呢?
似乎createEventListenerWrapperWithPriority这个表达式名现在说单单了究竟:依据服务缓冲器端成立一个惨剧国安局盒装缓冲器。有两个着重:服务缓冲器端和惨剧国安局盒装缓冲器。这当中的的服务缓冲器端是特指惨剧服务缓冲器端(关于惨剧服务缓冲器端的详尽介绍请求移步React当中的服务缓冲器端 )。
惨剧服务缓冲器端是根据惨剧的交互以往界定的,服务缓冲器端和惨剧名的映射关系存在于一个Map构造当中。createEventListenerWrapperWithPriority可能会根据惨剧名或者当中叶的服务缓冲器端返回多种不同最高级别的惨剧国安局盒装缓冲器。
总的来说,可能会有三种惨剧国安局盒装缓冲器:
dispatchDiscreteEvent: 妥善处理DFT惨剧 dispatchUserBlockingUpdate:妥善处理软件情况严重惨剧 dispatchEvent:妥善处理近十年惨剧这些盒装缓冲器是似乎可选到root上的惨剧国安局缓冲器listener,它们持有者各自的服务缓冲器端,当完全完全一致的惨剧可能会有时,codice_的似乎是这个值得注意服务缓冲器端的惨剧国安局。
透传惨剧可执行下一阶段红色
到这当中的我们可先梳理一下,root上可选的是这个持有者服务缓冲器端的惨剧国安局,可能会有它可能会使模块当中真实的惨剧得以可能会有。但到在此之前有一点并未包含在内,也就是惨剧可执行下一阶段的区隔。模块当中申领惨剧虽然可以以惨剧名 + “Capture”后缀的形式区隔将来的可执行下一阶段,但这和似乎可执行惨剧似乎是两回事,所以今天总括如何将申领惨剧时显式表示遗憾的可执行下一阶段似乎跟进到可执行惨剧的举动上。
关于这一点我们可以注目createEventListenerWrapperWithPriority表达式当中的其当中一个入荐:eventSystemFlags。它是惨剧控制系统的一个红色,纪录惨剧的各种标记,其当中一个标记就是IS_CAPTURE_PHASE,这表明了举例来说的惨剧是捉到下一阶段可能会有。当惨剧名掺入Capture后缀时,eventSystemFlags可能会被赋值为IS_CAPTURE_PHASE。
便在以服务缓冲器端成立可选到root上的惨剧国安局时,eventSystemFlags可能会作为它可执行时的入荐,传递偷偷地。因此,在惨剧可能会有的时候就可以告诉他模块当中的惨剧是以冒泡或是捉到的依序可执行。
function dispatchDiscreteEvent(
domEventName,
eventSystemFlags,
container,
nativeEvent,
) {
discreteUpdates(
dispatchEvent,
domEventName,
eventSystemFlags, // 当中叶惨剧可执行下一阶段的红色
container,
nativeEvent,
);
}
小结
今天我们应该能清楚两点:
惨剧妥善处理表达式不是可选到模块的表达方式上的,而是可选到root上,这和fiber树是的构造特征有关,即惨剧妥善处理表达式只能作为fiber的prop。 可选到root上的惨剧国安局不是我们在模块当中的写的惨剧妥善处理表达式,而是一个持有者惨剧服务缓冲器端,并能传递惨剧可执行下一阶段红色的国安局缓冲器。在此之前,申领下一阶段的指导现在完成,请注意可能会说是一说是惨剧是如何被可能会有的,让我们从可选到root上的国安局缓冲器侧面,想到它动手了什么。
惨剧可能会有 - 惨剧国安局缓冲器listener动手了什么
它动手的坏事可以用一句话说明了:都由以多种不同的服务缓冲器端权重来可能会有似乎的惨剧流程,并传递惨剧可执行下一阶段红色(eventSystemFlags)。
比如一个表达方式可选了onClick惨剧,那么点选它的时候,可选在root上的listener可能会被可能会有,可能会就此使得模块当中的惨剧被可执行。
也就是说可选到root上的惨剧国安局listener只是相当于一个差遣官,它按照惨剧的服务缓冲器端去安在后在此之后的指导:惨剧普通人的裂解、将惨剧妥善处理表达式采集到可执行切线、 惨剧可执行,这样在后面的集中管理反复当中,scheduler才能获知举例来说任务的服务缓冲器端,然后展开时集中管理。
如何将服务缓冲器端传递单单去?
借助于scheduler当中的runWithPriority表达式,通过codice_它,将服务缓冲器端纪录到借助于scheduler当中,所以集中管理缓冲器才能在集中管理的时候告诉他举例来说任务的服务缓冲器端。runWithPriority的第二个荐数,可能会去安在后请注意所述的三个指导。
以软件情况严重的服务缓冲器端最高级别为例:
function dispatchUserBlockingUpdate(
domEventName,
eventSystemFlags,
container,
nativeEvent,
) {
runWithPriority(
UserBlockingPriority,
dispatchEvent.bind(
null,
domEventName,
eventSystemFlags,
container,
nativeEvent,
),
);
}
dispatchUserBlockingUpdatecodice_runWithPriority,并当中叶UserBlockingPriority服务缓冲器端,这样就可以将UserBlockingPriority的服务缓冲器端纪录到Scheduler当中,不足之处React计算各种服务缓冲器端都是基于这个UserBlockingPriority服务缓冲器端。
除了传递服务缓冲器端,它动手的其它极其重要的坏事就是可能会有惨剧普通人的裂解、将惨剧妥善处理表达式采集到可执行切线、 惨剧可执行这三个反复,也就是到了惨剧的可执行下一阶段。root上的惨剧国安局就此可能会有的是dispatchEventsForPlugins。
这个表达式体可都是两部分:惨剧普通人的裂解和惨剧采集 、 惨剧可执行,涵盖了上述三个反复。
function dispatchEventsForPlugins(
domEventName: DOMEventName,
eventSystemFlags: EventSystemFlags,
nativeEvent: AnyNativeEvent,
targetInst: null | Fiber,
targetContainer: EventTarget,
): void {
const nativeEventTarget = getEventTarget(nativeEvent);
const dispatchQueue: DispatchQueue = [];
// 惨剧普通人的裂解,采集惨剧到可执行切线上
extractEvents(
dispatchQueue,
domEventName,
targetInst,
nativeEvent,
nativeEventTarget,
eventSystemFlags,
targetContainer,
);
// 可执行采集到的模块当中似乎的惨剧
processDispatchQueue(dispatchQueue, eventSystemFlags);
}
dispatchEventsForPlugins表达式当中惨剧的流转有一个极其重要的多种形式:dispatchQueue,它承载了本次裂解的惨剧普通人和采集到惨剧可执行切线上的惨剧妥善处理表达式。
listeners是惨剧可执行切线,event是裂解惨剧普通人,采集模块当中似乎的惨剧到可执行切线,以及惨剧普通人的裂解通过extractEvents动手到。
惨剧普通人的裂解和惨剧的采集
到这当中的我们应该清楚,root上的惨剧国安局被可能会意味著会激起惨剧普通人的裂解和惨剧的采集反复,这是为似乎的惨剧可能会有动手准备。
裂解惨剧普通人
在模块当中的惨剧妥善处理表达式当中到手的惨剧普通人并不是原生的惨剧普通人,而是经过React裂解的SyntheticEvent普通人。它解决了多种不同浏览缓冲器之间的兼容相异。抽象成实质上的惨剧普通人,解除Linux的心智经济负担。
惨剧可执行切线
当惨剧普通人裂解完毕,可能会将惨剧采集到惨剧可执行切线上。什么是惨剧可执行切线呢?
在浏览缓冲器的周边环境当中,若叔父长子表达方式可选了完全一致类别的惨剧,除非手动插手,【注目尚矽谷,得心应手学时IT】那么这些惨剧都可能会按照冒泡或者捉到的依序可能会有。
在React当中也是如此,从可能会有惨剧的表达方式开始,依据fiber树是的层级构造向上匹配,累加责成表达方式当中所有完全一致类别的惨剧,就此过渡到一个具有所有完全一致类别惨剧的操作符,这个操作符就是惨剧可执行切线。通过这个切线,React自己建模了一套惨剧捉到与冒泡的必要。
示意图是惨剧普通人的盒装和采集惨剧(冒泡的切线为例)的大抵反复
因为多种不同的惨剧可能会有多种不同的举动和妥善处理必要,所以裂解惨剧普通人的形态和采集惨剧到可执行切线必须通过插件动手到。总共有5种Plugin:SimpleEventPlugin,EnterLeeEventPlugin,ChangeEventPlugin,SelectEventPlugin,BeforeInputEventPlugin。它们的使命完全一样,只是妥善处理的惨剧类别多种不同,所以外部可能会有一些相异。本文只以SimpleEventPlugin为例来说是解这个反复,它妥善处理更为通用的惨剧类别,比如click、input、keydown等。
表列单单是SimpleEventPlugin当中形态裂解惨剧普通人并采集惨剧的示例。
function extractEvents(
dispatchQueue: DispatchQueue,
domEventName: DOMEventName,
targetInst: null | Fiber,
nativeEvent: AnyNativeEvent,
nativeEventTarget: null | EventTarget,
eventSystemFlags: EventSystemFlags,
targetContainer: EventTarget,
): void {
const reactName = topLevelEventsToReactNames.get(domEventName);
if (reactName === undefined) {
return;
}
let EventInterface;
switch (domEventName) {
// 赋值EventInterface(模块)
}
// 形态裂解惨剧普通人
const event = new SyntheticEvent(
reactName,
null,
nativeEvent,
nativeEventTarget,
EventInterface,
);
const inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0;
if (/*...*/) {
} else {
// scroll惨剧不冒泡
const accumulateTargetOnly =
!inCapturePhase &&
domEventName === 'scroll';
// 惨剧普通人试用 & 采集惨剧
accumulateSinglePhaseListeners(
targetInst,
dispatchQueue,
event,
inCapturePhase,
accumulateTargetOnly,
);
}
return event;
}
成立裂解惨剧普通人
这个实质上的惨剧普通人由SyntheticEvent表达式形态而成,它自己遵循W3C的规范又动手到了一遍浏览缓冲器的惨剧普通人模块,这样可以抹平相异,而原生的惨剧普通人却是是它的一个也就是说(nativeEvent)。
// 形态裂解惨剧普通人
const event = new SyntheticEvent(
reactName,
null,
nativeEvent,
nativeEventTarget,
EventInterface,
);
采集惨剧到可执行切线
这个反复是将模块当中似乎的惨剧妥善处理表达式采集到操作符当中,等待下一步的大批量可执行。
可先看一个例长子,远距离表达方式是counter,叔父级表达方式是counter-parent。
class EventDemo extends React.Component{
state = { count: 0 }
onDemoClick = () => {
console.log('counter的点选惨剧被可能会有了');
this.setState({
count: this.state.count + 1
})
}
onParentClick = () => {
console.log('叔父级表达方式的点选惨剧被可能会有了');
}
render() {
const { count } = this.state
return
className={'counter-parent'}
onClick={this.onParentClick}
>
onClick={this.onDemoClick}
className={'counter'}
>
{count}
}
}
当点选counter时,叔父表达方式上的点选惨剧也可能会被可能会有,相继打印单单:
'counter的点选惨剧被可能会有了'
'叔父级表达方式的点选惨剧被可能会有了'
实际上这是将惨剧以冒泡的依序采集到可执行切线便导致的。采集的反复由accumulateSinglePhaseListeners完成。
accumulateSinglePhaseListeners(
targetInst,
dispatchQueue,
event,
inCapturePhase,
accumulateTargetOnly,
);
表达式外部最极其重要的配置无疑是采集惨剧到可执行切线,为了动手到这一配置,必须在fiber树是当中从可能会有惨剧的光fiber终端开始,向上一直找单单root,过渡到一条清晰的冒泡或者捉到的切线。同时,沿途碰巧fiber终端时,根据惨剧名,从props当中受益我们似乎写在模块当中的惨剧妥善处理表达式,push到切线当中,等待下一步的大批量可执行。
请注意是该反复精简后的光码
export function accumulateSinglePhaseListeners(
targetFiber: Fiber | null,
dispatchQueue: DispatchQueue,
event: ReactSyntheticEvent,
inCapturePhase: boolean,
accumulateTargetOnly: boolean,
): void {
// 根据惨剧名来辨认是冒泡下一阶段的惨剧还是捉到下一阶段的惨剧
const bubbled = event._reactName;
const captured = bubbled !== null ? bubbled + 'Capture' : null;
// 表示遗憾存放惨剧国安局的操作符
const listeners: Array = [];
// 找单单远距离表达方式
let instance = targetFiber;
// 从远距离表达方式开始一直到root,累加所有的fiber普通人和惨剧国安局。
while (instance !== null) {
const {stateNode, tag} = instance;
if (tag === HostComponent && stateNode !== null) {
const currentTarget = stateNode;
// 惨剧捉到
if (captured !== null && inCapturePhase) {
// 从fiber当中受益惨剧妥善处理表达式
const captureListener = getListener(instance, captured);
if (captureListener != null) {
listeners.push(
createDispatchListener(instance, captureListener, currentTarget),
);
}
}
// 惨剧冒泡
if (bubbled !== null && !inCapturePhase) {
// 从fiber当中受益惨剧妥善处理表达式
const bubbleListener = getListener(instance, bubbled);
if (bubbleListener != null) {
listeners.push(
createDispatchListener(instance, bubbleListener, currentTarget),
);
}
}
}
instance = instance.return;
}
// 采集惨剧普通人
if (listeners.length !== 0) {
dispatchQueue.push(createDispatchEntry(event, listeners));
}
}
无论惨剧是在冒泡下一阶段可执行,还是捉到下一阶段可执行,都以同样的依序push到dispatchQueue的listeners当中,而冒泡或者捉到惨剧的可执行依序多种不同是由于移走listeners操作符的依序多种不同。
警惕,每次采集只可能会采集与惨剧光完全一致类别的惨剧,比如长子表达方式可选了onClick,叔父表达方式可选了onClick和onClickCapture:
className="parent"
onClick={onClickParent}
onClickCapture={onClickParentCapture}
>
叔父表达方式
className="child"
onClick={onClickChild}
>
长子表达方式
那么点选长子表达方式时,采集的将是onClickChild 和 onClickParent。
采集的结果如下
裂解惨剧普通人如何荐与到惨剧可执行反复
请注意我们说过,dispatchQueue的构造如请注意这样
[
{
event: SyntheticEvent,
listeners: [ listener1, listener2, ... ]
}
]
event就均是由着裂解惨剧普通人,可以将它视为是这些listeners共享的一个惨剧普通人。当移走listeners操作符可执行到每一个惨剧国安局表达式时,这个惨剧国安局可以改变event上的currentTarget,也可以codice_它请注意的stopPropagation方法来阻挠冒泡。event作为一个FTP被这些惨剧国安局消费品,消费品的举动遭遇在惨剧可执行时。
惨剧可执行
经过惨剧和惨剧普通人采集的反复,得到了一条清晰的惨剧可执行切线,还有一个被共享的惨剧普通人,便转回到惨剧可执行反复,没用尿素该切线,分作codice_每一项当中的国安局表达式。这个反复的着重在于惨剧冒泡和捉到的建模,以及裂解惨剧普通人的应用,如下就是指dispatchQueue当中提取单单惨剧普通人和时间可执行切线的反复。
export function processDispatchQueue(
dispatchQueue: DispatchQueue,
eventSystemFlags: EventSystemFlags,
): void {
const inCapturePhase = (eventSystemFlags & IS_CAPTURE_PHASE) !== 0;
for (let i = 0; i
// 从dispatchQueue当中取单单惨剧普通人和惨剧国安局操作符
const {event, listeners} = dispatchQueue[i];
// 将惨剧国安局交由processDispatchQueueItemsInOrder去可能会有,同时当中叶惨剧普通人供惨剧国安局用到
processDispatchQueueItemsInOrder(event, listeners, inCapturePhase);
}
// 捉到差错
rethrowCaughtError();
}
建模冒泡和捉到
冒泡和捉到的可执行依序是不一样的,但是可先前在采集惨剧的时候,无论是冒泡还是捉到,惨剧都是如此一来push到切线当中的的。那么可执行依序的相异是如何体现的呢?究竟是尿素切线的依序不一样导致了可执行依序各有多种不同。www.atguigu.com首可先回顾一下dispatchQueue当中的listeners当中的惨剧妥善处理表达式在后列依序:可能会有惨剧的远距离表达方式的惨剧妥善处理表达式在后在第一个,上层模块的惨剧妥善处理表达式分作更进一步在后。
叔父表达方式
长子表达方式
listeners: [ onClickChild, onClickParent ]
从左往左尿素的时候,远距离表达方式的惨剧可先可能会有,叔父表达方式惨剧分作可执行,这与冒泡的依序一样,那捉到的依序自然环境就是指左逆时针尿素了。建模冒泡和捉到可执行惨剧的示例如下:
其当中推论惨剧可执行下一阶段的依据inCapturePhase,它的来光在请注意的透传透传惨剧可执行下一阶段红色的素材当中的现在所述过。
function processDispatchQueueItemsInOrder(
event: ReactSyntheticEvent,
dispatchListeners: Array,
inCapturePhase: boolean,
): void {
let previousInstance;
if (inCapturePhase) {
// 惨剧捉到倒序尿素
for (let i = dispatchListeners.length - 1; i>= 0; i--) {
const {instance, currentTarget, listener} = dispatchListeners[i];
if (instance !== previousInstance && event.isPropagationStopped()) {
return;
}
// 可执行惨剧,当中叶event普通人,和currentTarget
executeDispatch(event, listener, currentTarget);
previousInstance = instance;
}
} else {
// 惨剧冒泡正序尿素
for (let i = 0; i
const {instance, currentTarget, listener} = dispatchListeners[i];
// 如果惨剧普通人阻挠了冒泡,则return丢尿素反复
if (instance !== previousInstance && event.isPropagationStopped()) {
return;
}
executeDispatch(event, listener, currentTarget);
previousInstance = instance;
}
}
}
自始,我们写在模块当中的惨剧妥善处理表达式就被可执行丢了,裂解惨剧普通人在这个反复当中充当了一个公共角色,每个惨剧可执行时,都可能会核查裂解惨剧普通人,有没有codice_阻挠冒泡的方法,另外可能会将举例来说挂载惨剧国安局的表达方式作为currentTarget挂载到惨剧普通人上,就此当中叶惨剧妥善处理表达式,我们得以受益到这个惨剧普通人。
概括
光码当中惨剧控制系统的示例量很大,我能活着单单来主要是带着这几个缺陷去看的示例:可选惨剧的反复是怎么样的、惨剧控制系统和服务缓冲器端的连系、似乎的惨剧妥善处理表达式到底如何可执行的。
概括一下惨剧必要的原理:由于fiber树是的特征,一个模块如果掺入惨剧的prop,那么将可能会在完全完全一致fiber终端的commit下一阶段可选一个惨剧国安局到root上,这个惨剧国安局是持有者服务缓冲器端的,这将它和服务缓冲器端必要连系了紧紧,可以把裂解惨剧必要当作一个协调者,都由去协调裂解惨剧普通人、采集惨剧、可能会有似乎的惨剧妥善处理表达式这三个反复。
文章来光于React当华文社区
推荐选读:
前端开发之React构建进阶学时习
前端React 开发当中只能告诉他的5个技巧
前端开发之多周边环境下react的配置
前端开发当中必须掌握的开发构建React
。男性脱发严重怎么治疗轻度中暑怎么解决
月经有血块
看病人营养品
膝关节炎的药物治疗
什么血糖仪比较准
常乐康和亿活哪个好
家用血糖仪哪个好
哪种血糖仪最准价格是多少
艾司奥美拉唑和金奥康哪个好
-
在绝望中会寻找希望
米槌不得了 佼佼者 佼佼者 题图唐高祖前段时间,“你而就会可以显然中就会国女足”,“你而就会可以显然中就会国速滑速滑”等等,类似“你而就会可以显然XXX”的句式频频
- 到厦门SM广场放题餐厅大吃一顿,352元顶配,甜品海鲜自由,一盘和牛吃回本
- 祥和实业原是1笔大宗交易 共成交4,196.80万元
- 网购到变质火腿肠被客服攻击学历 网友看吐:涉事客服停职
- 佳肴推荐:麻香鸡,霸王猪蹄,干锅兔的做法
- 投资者提问:你好董秘,贵公司多次阐述高度重视和关注辐照技术在对疑收纳有新冠...
- 进群可免费领取吸尘器? 有人信以为真 债主40余万元
- 投资者反问:华大基因有检测奥密克戎产品吗?
- 甜品推荐:麻辣鸡丝,老干妈烧冬瓜,芝士肉酱番茄盅的做法
- 新华全媒+|“格桑花”绽放东南,他们离家是为了更好地出门……
- 投资者提问:董秘你好,永安已经投放氢能自行车系统,公司加快节奏赶上,冬奥会...