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 { getIonMode } from '../../global/ionic-global';
|
||||||
import { Color, ScrollBaseDetail, ScrollDetail } from '../../interface';
|
import { Color, ScrollBaseDetail, ScrollDetail } from '../../interface';
|
||||||
|
import { componentOnReady } from '../../utils/helpers';
|
||||||
import { isPlatform } from '../../utils/platform';
|
import { isPlatform } from '../../utils/platform';
|
||||||
import { createColorClasses, hostContext } from '../../utils/theme';
|
import { createColorClasses, hostContext } from '../../utils/theme';
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ export class Content implements ComponentInterface {
|
|||||||
private queued = false;
|
private queued = false;
|
||||||
private cTop = -1;
|
private cTop = -1;
|
||||||
private cBottom = -1;
|
private cBottom = -1;
|
||||||
private scrollEl!: HTMLElement;
|
private scrollEl?: HTMLElement;
|
||||||
private isMainContent = true;
|
private isMainContent = true;
|
||||||
|
|
||||||
// Detail is used in a hot loop in the scroll event, by allocating it here
|
// 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 => {
|
readTask(ts => {
|
||||||
this.queued = false;
|
this.queued = false;
|
||||||
this.detail.event = ev;
|
this.detail.event = ev;
|
||||||
updateScrollDetail(this.detail, this.scrollEl, ts, shouldStart);
|
updateScrollDetail(this.detail, this.scrollEl!, ts, shouldStart);
|
||||||
this.ionScroll.emit(this.detail);
|
this.ionScroll.emit(this.detail);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -183,8 +184,16 @@ export class Content implements ComponentInterface {
|
|||||||
* and `scrollToPoint()` to scroll the content into a certain point.
|
* and `scrollToPoint()` to scroll the content into a certain point.
|
||||||
*/
|
*/
|
||||||
@Method()
|
@Method()
|
||||||
getScrollElement(): Promise<HTMLElement> {
|
async getScrollElement(): Promise<HTMLElement> {
|
||||||
return Promise.resolve(this.scrollEl);
|
/**
|
||||||
|
* 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`.
|
* @param duration The amount of time to take scrolling to the bottom. Defaults to `0`.
|
||||||
*/
|
*/
|
||||||
@Method()
|
@Method()
|
||||||
scrollToBottom(duration = 0): Promise<void> {
|
async scrollToBottom(duration = 0): Promise<void> {
|
||||||
const y = this.scrollEl.scrollHeight - this.scrollEl.clientHeight;
|
const scrollEl = await this.getScrollElement();
|
||||||
|
const y = scrollEl!.scrollHeight - scrollEl!.clientHeight;
|
||||||
return this.scrollToPoint(undefined, y, duration);
|
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.
|
* @param duration The amount of time to take scrolling by that amount.
|
||||||
*/
|
*/
|
||||||
@Method()
|
@Method()
|
||||||
scrollByPoint(x: number, y: number, duration: number): Promise<void> {
|
async scrollByPoint(x: number, y: number, duration: number): Promise<void> {
|
||||||
return this.scrollToPoint(x + this.scrollEl.scrollLeft, y + this.scrollEl.scrollTop, duration);
|
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()
|
@Method()
|
||||||
async scrollToPoint(x: number | undefined | null, y: number | undefined | null, duration = 0): Promise<void> {
|
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 (duration < 32) {
|
||||||
if (y != null) {
|
if (y != null) {
|
||||||
el.scrollTop = y;
|
el.scrollTop = y;
|
||||||
|
|||||||
Reference in New Issue
Block a user