mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-10 00:27:41 +08:00
fix(content): ensure scrollEl is always available in scroll methods (#24255)
This commit is contained in:
@ -2,6 +2,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, List
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { Color, ScrollBaseDetail, ScrollDetail } from '../../interface';
|
||||
import { componentOnReady } from '../../utils/helpers';
|
||||
import { isPlatform } from '../../utils/platform';
|
||||
import { createColorClasses, hostContext } from '../../utils/theme';
|
||||
|
||||
@ -25,7 +26,7 @@ export class Content implements ComponentInterface {
|
||||
private queued = false;
|
||||
private cTop = -1;
|
||||
private cBottom = -1;
|
||||
private scrollEl!: HTMLElement;
|
||||
private scrollEl?: HTMLElement;
|
||||
private isMainContent = true;
|
||||
|
||||
// Detail is used in a hot loop in the scroll event, by allocating it here
|
||||
@ -168,7 +169,7 @@ export class Content implements ComponentInterface {
|
||||
readTask(ts => {
|
||||
this.queued = false;
|
||||
this.detail.event = ev;
|
||||
updateScrollDetail(this.detail, this.scrollEl, ts, shouldStart);
|
||||
updateScrollDetail(this.detail, this.scrollEl!, ts, shouldStart);
|
||||
this.ionScroll.emit(this.detail);
|
||||
});
|
||||
}
|
||||
@ -183,8 +184,16 @@ export class Content implements ComponentInterface {
|
||||
* and `scrollToPoint()` to scroll the content into a certain point.
|
||||
*/
|
||||
@Method()
|
||||
getScrollElement(): Promise<HTMLElement> {
|
||||
return Promise.resolve(this.scrollEl);
|
||||
async getScrollElement(): Promise<HTMLElement> {
|
||||
/**
|
||||
* If this gets called in certain early lifecycle hooks (ex: Vue onMounted),
|
||||
* scrollEl won't be defined yet with the custom elements build, so wait for it to load in.
|
||||
*/
|
||||
if (!this.scrollEl) {
|
||||
await new Promise(resolve => componentOnReady(this.el, resolve));
|
||||
}
|
||||
|
||||
return Promise.resolve(this.scrollEl!);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -203,8 +212,9 @@ export class Content implements ComponentInterface {
|
||||
* @param duration The amount of time to take scrolling to the bottom. Defaults to `0`.
|
||||
*/
|
||||
@Method()
|
||||
scrollToBottom(duration = 0): Promise<void> {
|
||||
const y = this.scrollEl.scrollHeight - this.scrollEl.clientHeight;
|
||||
async scrollToBottom(duration = 0): Promise<void> {
|
||||
const scrollEl = await this.getScrollElement();
|
||||
const y = scrollEl!.scrollHeight - scrollEl!.clientHeight;
|
||||
return this.scrollToPoint(undefined, y, duration);
|
||||
}
|
||||
|
||||
@ -216,8 +226,9 @@ export class Content implements ComponentInterface {
|
||||
* @param duration The amount of time to take scrolling by that amount.
|
||||
*/
|
||||
@Method()
|
||||
scrollByPoint(x: number, y: number, duration: number): Promise<void> {
|
||||
return this.scrollToPoint(x + this.scrollEl.scrollLeft, y + this.scrollEl.scrollTop, duration);
|
||||
async scrollByPoint(x: number, y: number, duration: number): Promise<void> {
|
||||
const scrollEl = await this.getScrollElement();
|
||||
return this.scrollToPoint(x + scrollEl!.scrollLeft, y + scrollEl!.scrollTop, duration);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -229,7 +240,7 @@ export class Content implements ComponentInterface {
|
||||
*/
|
||||
@Method()
|
||||
async scrollToPoint(x: number | undefined | null, y: number | undefined | null, duration = 0): Promise<void> {
|
||||
const el = this.scrollEl;
|
||||
const el = await this.getScrollElement();
|
||||
if (duration < 32) {
|
||||
if (y != null) {
|
||||
el.scrollTop = y;
|
||||
|
||||
Reference in New Issue
Block a user