mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 18:17:31 +08:00
perf(many): reduce delay when performing overlay or page transitions (#26189)
resolves #24346
This commit is contained in:
@ -271,7 +271,6 @@ export class StackController {
|
|||||||
|
|
||||||
if ((containerEl as any).commit) {
|
if ((containerEl as any).commit) {
|
||||||
return containerEl.commit(enteringEl, leavingEl, {
|
return containerEl.commit(enteringEl, leavingEl, {
|
||||||
deepWait: true,
|
|
||||||
duration: direction === undefined ? 0 : undefined,
|
duration: direction === undefined ? 0 : undefined,
|
||||||
direction,
|
direction,
|
||||||
showGoBack,
|
showGoBack,
|
||||||
|
@ -17,7 +17,7 @@ import type {
|
|||||||
} from '../../interface';
|
} from '../../interface';
|
||||||
import { findIonContent, printIonContentErrorMsg } from '../../utils/content';
|
import { findIonContent, printIonContentErrorMsg } from '../../utils/content';
|
||||||
import { CoreDelegate, attachComponent, detachComponent } from '../../utils/framework-delegate';
|
import { CoreDelegate, attachComponent, detachComponent } from '../../utils/framework-delegate';
|
||||||
import { raf, inheritAttributes } from '../../utils/helpers';
|
import { raf, inheritAttributes, hasLazyBuild } from '../../utils/helpers';
|
||||||
import type { Attributes } from '../../utils/helpers';
|
import type { Attributes } from '../../utils/helpers';
|
||||||
import { KEYBOARD_DID_OPEN } from '../../utils/keyboard/keyboard';
|
import { KEYBOARD_DID_OPEN } from '../../utils/keyboard/keyboard';
|
||||||
import { printIonWarning } from '../../utils/logging';
|
import { printIonWarning } from '../../utils/logging';
|
||||||
@ -436,7 +436,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { presentingElement } = this;
|
const { presentingElement, el } = this;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When using an inline modal
|
* When using an inline modal
|
||||||
@ -462,9 +462,8 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const { inline, delegate } = this.getDelegate(true);
|
const { inline, delegate } = this.getDelegate(true);
|
||||||
this.usersElement = await attachComponent(delegate, this.el, this.component, ['ion-page'], data, inline);
|
this.usersElement = await attachComponent(delegate, el, this.component, ['ion-page'], data, inline);
|
||||||
|
hasLazyBuild(el) && (await deepReady(this.usersElement));
|
||||||
await deepReady(this.usersElement);
|
|
||||||
|
|
||||||
writeTask(() => this.el.classList.add('show-modal'));
|
writeTask(() => this.el.classList.add('show-modal'));
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ import type {
|
|||||||
TriggerAction,
|
TriggerAction,
|
||||||
} from '../../interface';
|
} from '../../interface';
|
||||||
import { CoreDelegate, attachComponent, detachComponent } from '../../utils/framework-delegate';
|
import { CoreDelegate, attachComponent, detachComponent } from '../../utils/framework-delegate';
|
||||||
import { addEventListener, raf } from '../../utils/helpers';
|
import { addEventListener, raf, hasLazyBuild } from '../../utils/helpers';
|
||||||
import { BACKDROP, dismiss, eventMethod, focusFirstDescendant, prepareOverlay, present } from '../../utils/overlays';
|
import { BACKDROP, dismiss, eventMethod, focusFirstDescendant, prepareOverlay, present } from '../../utils/overlays';
|
||||||
import { isPlatform } from '../../utils/platform';
|
import { isPlatform } from '../../utils/platform';
|
||||||
import { getClassMap } from '../../utils/theme';
|
import { getClassMap } from '../../utils/theme';
|
||||||
@ -431,14 +431,16 @@ export class Popover implements ComponentInterface, PopoverInterface {
|
|||||||
await this.currentTransition;
|
await this.currentTransition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { el } = this;
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
...this.componentProps,
|
...this.componentProps,
|
||||||
popover: this.el,
|
popover: this.el,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { inline, delegate } = this.getDelegate(true);
|
const { inline, delegate } = this.getDelegate(true);
|
||||||
this.usersElement = await attachComponent(delegate, this.el, this.component, ['popover-viewport'], data, inline);
|
this.usersElement = await attachComponent(delegate, el, this.component, ['popover-viewport'], data, inline);
|
||||||
await deepReady(this.usersElement);
|
hasLazyBuild(el) && (await deepReady(this.usersElement));
|
||||||
|
|
||||||
if (!this.keyboardEvents) {
|
if (!this.keyboardEvents) {
|
||||||
this.configureKeyboardInteraction();
|
this.configureKeyboardInteraction();
|
||||||
|
@ -19,7 +19,7 @@ import type {
|
|||||||
} from '../../interface';
|
} from '../../interface';
|
||||||
import { getTimeGivenProgression } from '../../utils/animation/cubic-bezier';
|
import { getTimeGivenProgression } from '../../utils/animation/cubic-bezier';
|
||||||
import { attachComponent, detachComponent } from '../../utils/framework-delegate';
|
import { attachComponent, detachComponent } from '../../utils/framework-delegate';
|
||||||
import { shallowEqualStringMap } from '../../utils/helpers';
|
import { shallowEqualStringMap, hasLazyBuild } from '../../utils/helpers';
|
||||||
import { transition } from '../../utils/transition';
|
import { transition } from '../../utils/transition';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -238,6 +238,13 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
|
|||||||
enteringEl,
|
enteringEl,
|
||||||
leavingEl,
|
leavingEl,
|
||||||
baseEl: el,
|
baseEl: el,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We need to wait for all Stencil components
|
||||||
|
* to be ready only when using the lazy
|
||||||
|
* loaded bundle.
|
||||||
|
*/
|
||||||
|
deepWait: hasLazyBuild(el),
|
||||||
progressCallback: opts.progressAnimation
|
progressCallback: opts.progressAnimation
|
||||||
? (ani) => {
|
? (ani) => {
|
||||||
/**
|
/**
|
||||||
|
@ -76,6 +76,15 @@ export const componentOnReady = (el: any, callback: any) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This functions checks if a Stencil component is using
|
||||||
|
* the lazy loaded build of Stencil. Returns `true` if
|
||||||
|
* the component is lazy loaded. Returns `false` otherwise.
|
||||||
|
*/
|
||||||
|
export const hasLazyBuild = (stencilEl: HTMLElement) => {
|
||||||
|
return (stencilEl as any).componentOnReady !== undefined;
|
||||||
|
};
|
||||||
|
|
||||||
export type Attributes = { [key: string]: any };
|
export type Attributes = { [key: string]: any };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
LIFECYCLE_WILL_LEAVE,
|
LIFECYCLE_WILL_LEAVE,
|
||||||
} from '../../components/nav/constants';
|
} from '../../components/nav/constants';
|
||||||
import type { Animation, AnimationBuilder, NavDirection, NavOptions } from '../../interface';
|
import type { Animation, AnimationBuilder, NavDirection, NavOptions } from '../../interface';
|
||||||
import { componentOnReady, raf } from '../helpers';
|
import { raf } from '../helpers';
|
||||||
|
|
||||||
const iosTransitionAnimation = () => import('./ios.transition');
|
const iosTransitionAnimation = () => import('./ios.transition');
|
||||||
const mdTransitionAnimation = () => import('./md.transition');
|
const mdTransitionAnimation = () => import('./md.transition');
|
||||||
@ -135,11 +135,11 @@ const noAnimation = async (opts: TransitionOptions): Promise<TransitionResult> =
|
|||||||
|
|
||||||
const waitForReady = async (opts: TransitionOptions, defaultDeep: boolean) => {
|
const waitForReady = async (opts: TransitionOptions, defaultDeep: boolean) => {
|
||||||
const deep = opts.deepWait !== undefined ? opts.deepWait : defaultDeep;
|
const deep = opts.deepWait !== undefined ? opts.deepWait : defaultDeep;
|
||||||
const promises = deep
|
|
||||||
? [deepReady(opts.enteringEl), deepReady(opts.leavingEl)]
|
|
||||||
: [shallowReady(opts.enteringEl), shallowReady(opts.leavingEl)];
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
if (deep) {
|
||||||
|
await Promise.all([deepReady(opts.enteringEl), deepReady(opts.leavingEl)]);
|
||||||
|
}
|
||||||
|
|
||||||
await notifyViewReady(opts.viewIsReady, opts.enteringEl);
|
await notifyViewReady(opts.viewIsReady, opts.enteringEl);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -195,13 +195,6 @@ export const lifecycle = (el: HTMLElement | undefined, eventName: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const shallowReady = (el: Element | undefined): Promise<any> => {
|
|
||||||
if (el) {
|
|
||||||
return new Promise((resolve) => componentOnReady(el, resolve));
|
|
||||||
}
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
|
|
||||||
export const deepReady = async (el: any | undefined): Promise<void> => {
|
export const deepReady = async (el: any | undefined): Promise<void> => {
|
||||||
const element = el as any;
|
const element = el as any;
|
||||||
if (element) {
|
if (element) {
|
||||||
|
@ -365,7 +365,6 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
|
|||||||
}
|
}
|
||||||
|
|
||||||
await routerOutlet.commit(enteringEl, leavingEl, {
|
await routerOutlet.commit(enteringEl, leavingEl, {
|
||||||
deepWait: true,
|
|
||||||
duration: skipTransition || directionToUse === undefined ? 0 : undefined,
|
duration: skipTransition || directionToUse === undefined ? 0 : undefined,
|
||||||
direction: directionToUse,
|
direction: directionToUse,
|
||||||
showGoBack: !!routeInfo.pushedByRoute,
|
showGoBack: !!routeInfo.pushedByRoute,
|
||||||
|
@ -195,7 +195,7 @@ export const IonRouterOutlet = /*@__PURE__*/ defineComponent({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const transition = (
|
const transition = async (
|
||||||
enteringEl: HTMLElement,
|
enteringEl: HTMLElement,
|
||||||
leavingEl: HTMLElement,
|
leavingEl: HTMLElement,
|
||||||
direction: any, // TODO types
|
direction: any, // TODO types
|
||||||
@ -203,42 +203,35 @@ export const IonRouterOutlet = /*@__PURE__*/ defineComponent({
|
|||||||
progressAnimation: boolean,
|
progressAnimation: boolean,
|
||||||
animationBuilder?: AnimationBuilder
|
animationBuilder?: AnimationBuilder
|
||||||
) => {
|
) => {
|
||||||
return new Promise(resolve => {
|
if (skipTransition) {
|
||||||
if (skipTransition) {
|
skipTransition = false;
|
||||||
skipTransition = false;
|
return Promise.resolve(false);
|
||||||
return resolve(false);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (enteringEl === leavingEl) {
|
if (enteringEl === leavingEl) {
|
||||||
return resolve(false);
|
return Promise.resolve(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
enteringEl.classList.add('ion-page-invisible');
|
||||||
requestAnimationFrame(async () => {
|
|
||||||
enteringEl.classList.add('ion-page-invisible');
|
|
||||||
|
|
||||||
const hasRootDirection = direction === undefined || direction === 'root' || direction === 'none';
|
const hasRootDirection = direction === undefined || direction === 'root' || direction === 'none';
|
||||||
const result = await ionRouterOutlet.value.commit(enteringEl, leavingEl, {
|
const result = await ionRouterOutlet.value.commit(enteringEl, leavingEl, {
|
||||||
deepWait: true,
|
/**
|
||||||
/**
|
* replace operations result in a direction of none.
|
||||||
* replace operations result in a direction of none.
|
* These typically do not have need animations, so we set
|
||||||
* These typically do not have need animations, so we set
|
* the duration to 0. However, if a developer explicitly
|
||||||
* the duration to 0. However, if a developer explicitly
|
* passes an animationBuilder, we should assume that
|
||||||
* passes an animationBuilder, we should assume that
|
* they want an animation to be played even
|
||||||
* they want an animation to be played even
|
* though it is a replace operation.
|
||||||
* though it is a replace operation.
|
*/
|
||||||
*/
|
duration: hasRootDirection && animationBuilder === undefined ? 0 : undefined,
|
||||||
duration: hasRootDirection && animationBuilder === undefined ? 0 : undefined,
|
direction,
|
||||||
direction,
|
showGoBack,
|
||||||
showGoBack,
|
progressAnimation,
|
||||||
progressAnimation,
|
animationBuilder
|
||||||
animationBuilder
|
|
||||||
});
|
|
||||||
|
|
||||||
return resolve(result);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handlePageTransition = async () => {
|
const handlePageTransition = async () => {
|
||||||
|
Reference in New Issue
Block a user