perf(virtual-scroll): scroll events

This commit is contained in:
Manu Mtz.-Almeida
2018-02-09 18:14:06 +01:00
parent 9226684826
commit 3d5abffdd6
7 changed files with 36 additions and 74 deletions

View File

@ -759,9 +759,6 @@ declare global {
namespace JSXElements { namespace JSXElements {
export interface IonContentAttributes extends HTMLAttributes { export interface IonContentAttributes extends HTMLAttributes {
fullscreen?: boolean; fullscreen?: boolean;
ionScroll?: Function;
ionScrollEnd?: Function;
ionScrollStart?: Function;
} }
} }
} }
@ -2530,10 +2527,10 @@ declare global {
} }
namespace JSXElements { namespace JSXElements {
export interface IonScrollAttributes extends HTMLAttributes { export interface IonScrollAttributes extends HTMLAttributes {
disabled?: boolean;
onionScroll?: ScrollCallback; onionScroll?: ScrollCallback;
onionScrollEnd?: ScrollCallback; onionScrollEnd?: ScrollCallback;
onionScrollStart?: ScrollCallback; onionScrollStart?: ScrollCallback;
scrollEvents?: boolean;
} }
} }
} }

View File

@ -25,21 +25,6 @@ export class Content {
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController; @Prop({ context: 'dom' }) dom: DomController;
/**
* Emitted when the scrolling first starts.
*/
@Prop() ionScrollStart: Function;
/**
* Emitted on every scroll event.
*/
@Prop() ionScroll: Function;
/**
* Emitted when scrolling ends.
*/
@Prop() ionScrollEnd: Function;
/** /**
* If true, the content will scroll behind the headers * If true, the content will scroll behind the headers
* and footers. This effect can easily be seen by setting the toolbar * and footers. This effect can easily be seen by setting the toolbar

View File

@ -25,27 +25,6 @@ and footers. This effect can easily be seen by setting the toolbar
to transparent. to transparent.
#### ionScroll
Emitted on every scroll event.
#### ionScrollEnd
Emitted when scrolling ends.
#### ionScrollStart
Emitted when the scrolling first starts.
## Attributes ## Attributes
#### fullscreen #### fullscreen
@ -57,27 +36,6 @@ and footers. This effect can easily be seen by setting the toolbar
to transparent. to transparent.
#### ion-scroll
Emitted on every scroll event.
#### ion-scroll-end
Emitted when scrolling ends.
#### ion-scroll-start
Emitted when the scrolling first starts.
## Methods ## Methods
#### scrollToBottom() #### scrollToBottom()

View File

@ -227,6 +227,9 @@ export class InfiniteScroll {
private enableScrollEvents(shouldListen: boolean) { private enableScrollEvents(shouldListen: boolean) {
if (this.scrollEl) { if (this.scrollEl) {
if (shouldListen) {
this.scrollEl.scrollEvents = true;
}
this.enableListener(this, 'ionScroll', shouldListen, this.scrollEl); this.enableListener(this, 'ionScroll', shouldListen, this.scrollEl);
} }
} }

View File

@ -1,4 +1,4 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Component, Element, Event, EventEmitter, EventListenerEnable, Listen, Method, Prop, Watch } from '@stencil/core';
import { Config, DomController, GestureDetail } from '../../index'; import { Config, DomController, GestureDetail } from '../../index';
import { GestureController, GestureDelegate } from '../gesture-controller/gesture-controller'; import { GestureController, GestureDelegate } from '../gesture-controller/gesture-controller';
@ -21,11 +21,10 @@ export class Scroll {
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@Prop({ context: 'config'}) config: Config; @Prop({ context: 'config'}) config: Config;
@Prop({ context: 'enableListener'}) enableListener: EventListenerEnable;
@Prop({ context: 'dom' }) dom: DomController; @Prop({ context: 'dom' }) dom: DomController;
@Prop({ context: 'isServer' }) isServer: boolean; @Prop({ context: 'isServer' }) isServer: boolean;
@Prop() disabled = false;
@Prop() onionScrollStart: ScrollCallback; @Prop() onionScrollStart: ScrollCallback;
@Prop() onionScroll: ScrollCallback; @Prop() onionScroll: ScrollCallback;
@Prop() onionScrollEnd: ScrollCallback; @Prop() onionScrollEnd: ScrollCallback;
@ -45,6 +44,13 @@ export class Scroll {
*/ */
@Event() ionScrollEnd: EventEmitter; @Event() ionScrollEnd: EventEmitter;
@Prop() scrollEvents = false;
@Watch('scrollEvents')
scrollChanged(enabled: boolean) {
this.enableListener(this, 'scroll', enabled);
}
componentDidLoad() { componentDidLoad() {
if (this.isServer) { if (this.isServer) {
return; return;
@ -53,6 +59,7 @@ export class Scroll {
const gestureCtrl = Ionic.gesture = Ionic.gesture || new GestureController(); const gestureCtrl = Ionic.gesture = Ionic.gesture || new GestureController();
this.gesture = gestureCtrl.createGesture('scroll', 100, false); this.gesture = gestureCtrl.createGesture('scroll', 100, false);
this.app = this.el.closest('ion-app') as HTMLIonAppElement; this.app = this.el.closest('ion-app') as HTMLIonAppElement;
this.scrollChanged(this.scrollEvents);
} }
componentDidUnload() { componentDidUnload() {
@ -62,7 +69,7 @@ export class Scroll {
// Native Scroll ************************* // Native Scroll *************************
@Listen('scroll', { passive: true }) @Listen('scroll', { passive: true, enabled: false })
onNativeScroll() { onNativeScroll() {
if (!this.queued) { if (!this.queued) {
this.queued = true; this.queued = true;

View File

@ -21,10 +21,10 @@ export const enum NodeChange {
} }
export interface Cell { export interface Cell {
type: CellType;
value: any;
i: number; i: number;
index: number; index: number;
value: any;
type: CellType;
height: number; height: number;
reads: number; reads: number;
visible: boolean; visible: boolean;
@ -35,6 +35,7 @@ export interface VirtualNode {
top: number; top: number;
change: NodeChange; change: NodeChange;
d: boolean; d: boolean;
visible: boolean;
} }
const MIN_READS = 2; const MIN_READS = 2;
@ -88,6 +89,7 @@ export function updateVDom(dom: VirtualNode[], heightIndex: Uint32Array, cells:
dom.push({ dom.push({
d: false, d: false,
cell: cell, cell: cell,
visible: true,
change: NodeChange.Cell, change: NodeChange.Cell,
top: heightIndex[index], top: heightIndex[index],
}); });
@ -106,8 +108,10 @@ export function doRender(
el: HTMLElement, el: HTMLElement,
itemRender: ItemRenderFn, itemRender: ItemRenderFn,
dom: VirtualNode[], dom: VirtualNode[],
updateCellHeight: Function) { updateCellHeight: Function
) {
const children = el.children; const children = el.children;
const childrenNu = children.length;
let child: HTMLElement; let child: HTMLElement;
for (let i = 0; i < dom.length; i++) { for (let i = 0; i < dom.length; i++) {
const node = dom[i]; const node = dom[i];
@ -115,7 +119,7 @@ export function doRender(
// the cell change, the content must be updated // the cell change, the content must be updated
if (node.change === NodeChange.Cell) { if (node.change === NodeChange.Cell) {
if (i < children.length) { if (i < childrenNu) {
child = children[i] as HTMLElement; child = children[i] as HTMLElement;
itemRender(child, cell, i); itemRender(child, cell, i);
} else { } else {
@ -132,13 +136,22 @@ export function doRender(
if (node.change !== NodeChange.NoChange) { if (node.change !== NodeChange.NoChange) {
child.style.transform = `translate3d(0,${node.top}px,0)`; child.style.transform = `translate3d(0,${node.top}px,0)`;
} }
if (cell.visible) {
child.classList.remove('virtual-loading'); // update visibility
} else { const visible = cell.visible;
child.classList.add('virtual-loading'); if (node.visible !== visible) {
if (visible) {
child.classList.remove('virtual-loading');
} else {
child.classList.add('virtual-loading');
}
node.visible = visible;
} }
// dynamic height inference
if (cell.reads > 0) { if (cell.reads > 0) {
updateCellHeight(cell, child); updateCellHeight(cell, child);
cell.reads--;
} }
} }
} }

View File

@ -228,7 +228,6 @@ export class VirtualScroll {
return; return;
} }
cell.visible = true; cell.visible = true;
cell.reads--;
if (cell.height !== height) { if (cell.height !== height) {
console.debug(`[${cell.reads}] cell size ${cell.height} -> ${height}`); console.debug(`[${cell.reads}] cell size ${cell.height} -> ${height}`);
cell.height = height; cell.height = height;