From 57b1e518d50b5a73472508bee71bd4da899c44c5 Mon Sep 17 00:00:00 2001 From: bonkalol Date: Wed, 7 Feb 2024 15:45:34 +0300 Subject: [PATCH] Fixed an issue where lifecycleDone could be emitted before the last render is done --- .../b-virtual-scroll-new.ts | 3 +++ .../base/b-virtual-scroll-new/handlers.ts | 24 +++++++++++++++---- .../interface/component.ts | 5 ++++ .../modules/state/index.ts | 16 +++++++++++++ .../test/unit/functional/emitter/payload.ts | 4 ++-- 5 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/components/base/b-virtual-scroll-new/b-virtual-scroll-new.ts b/src/components/base/b-virtual-scroll-new/b-virtual-scroll-new.ts index 37a5dbca56..0db29fb523 100644 --- a/src/components/base/b-virtual-scroll-new/b-virtual-scroll-new.ts +++ b/src/components/base/b-virtual-scroll-new/b-virtual-scroll-new.ts @@ -401,8 +401,11 @@ export default class bVirtualScrollNew extends iVirtualScrollHandlers implements }); }); + this.componentInternalState.setIsDomInsertInProgress(true); + this.async.requestAnimationFrame(() => { this.$refs.container.appendChild(fragment); + this.componentInternalState.setIsDomInsertInProgress(false); this.onDomInsertDone(); this.onRenderDone(); diff --git a/src/components/base/b-virtual-scroll-new/handlers.ts b/src/components/base/b-virtual-scroll-new/handlers.ts index 87c1a1bc92..575667ce7d 100644 --- a/src/components/base/b-virtual-scroll-new/handlers.ts +++ b/src/components/base/b-virtual-scroll-new/handlers.ts @@ -6,6 +6,8 @@ * https://github.com/V4Fire/Client/blob/master/LICENSE */ +import symbolGenerator from 'core/symbol'; + import iVirtualScrollProps from 'components/base/b-virtual-scroll-new/props'; import type bVirtualScrollNew from 'components/base/b-virtual-scroll-new/b-virtual-scroll-new'; @@ -16,6 +18,8 @@ import { isAsyncReplaceError } from 'components/base/b-virtual-scroll-new/module import iData, { component } from 'components/super/i-data/i-data'; +const $$ = symbolGenerator(); + /** * A class that provides an API to handle events emitted by the {@link bVirtualScrollNew} component. * This class is designed to work in conjunction with {@link bVirtualScrollNew}. @@ -97,15 +101,27 @@ export abstract class iVirtualScrollHandlers extends iVirtualScrollProps { */ protected onLifecycleDone(this: bVirtualScrollNew): void { const - state = this.getVirtualScrollState(); + state = this.getVirtualScrollState(), + isDomInsertInProgress = this.componentInternalState.getIsDomInsertInProgress(); if (state.isLifecycleDone) { return; } - this.slotsStateController.doneState(); - this.componentInternalState.setIsLifecycleDone(true); - this.componentEmitter.emit(componentEvents.lifecycleDone); + const handler = () => { + this.slotsStateController.doneState(); + this.componentInternalState.setIsLifecycleDone(true); + this.componentEmitter.emit(componentEvents.lifecycleDone); + }; + + if (isDomInsertInProgress) { + return this.componentEmitter.once(componentEvents.renderDone, handler, { + group: bVirtualScrollNewAsyncGroup, + label: $$.waitUntilRenderDone + }); + } + + return handler(); } /** diff --git a/src/components/base/b-virtual-scroll-new/interface/component.ts b/src/components/base/b-virtual-scroll-new/interface/component.ts index 863eb08eb2..8b4bf66eed 100644 --- a/src/components/base/b-virtual-scroll-new/interface/component.ts +++ b/src/components/base/b-virtual-scroll-new/interface/component.ts @@ -132,6 +132,11 @@ export interface PrivateComponentState { * Pointer to the index of the data element that was last rendered. */ dataOffset: number; + + /** + * If true, it means that the process of inserting components into the DOM tree is currently in progress. + */ + isDomInsertInProgress: boolean; } /** diff --git a/src/components/base/b-virtual-scroll-new/modules/state/index.ts b/src/components/base/b-virtual-scroll-new/modules/state/index.ts index 62fc98e086..f0d2b2a162 100644 --- a/src/components/base/b-virtual-scroll-new/modules/state/index.ts +++ b/src/components/base/b-virtual-scroll-new/modules/state/index.ts @@ -127,6 +127,14 @@ export class ComponentInternalState extends Friend { this.state.isInitialRender = value; } + /** + * Sets the flag indicating that the process of inserting components into the DOM tree is currently in progress + * @param value + */ + setIsDomInsertInProgress(value: boolean): void { + this.privateState.isDomInsertInProgress = value; + } + /** * Sets the flag indicating if requests are stopped and the component won't make any more requests * until the lifecycle is refreshed. @@ -190,6 +198,14 @@ export class ComponentInternalState extends Friend { return this.privateState.dataOffset; } + /** + * Returns the value of the flag indicating whether the process + * of inserting components into the DOM tree is currently in progress + */ + getIsDomInsertInProgress(): boolean { + return this.privateState.isDomInsertInProgress; + } + /** * Updates the cursor indicating the last index of the last rendered data element */ diff --git a/src/components/base/b-virtual-scroll-new/test/unit/functional/emitter/payload.ts b/src/components/base/b-virtual-scroll-new/test/unit/functional/emitter/payload.ts index 3c0e9d3d1a..3885b84083 100644 --- a/src/components/base/b-virtual-scroll-new/test/unit/functional/emitter/payload.ts +++ b/src/components/base/b-virtual-scroll-new/test/unit/functional/emitter/payload.ts @@ -161,9 +161,9 @@ test.describe('', () => { ['renderEngineStart'], ['renderEngineDone'], ['domInsertStart'], - ['lifecycleDone'], ['domInsertDone'], - ['renderDone'] + ['renderDone'], + ['lifecycleDone'] ]); }); });