From 3d5abffdd64cbe135b57af669e41075c1bd8cdd0 Mon Sep 17 00:00:00 2001 From: "Manu Mtz.-Almeida" Date: Fri, 9 Feb 2018 18:14:06 +0100 Subject: [PATCH] perf(virtual-scroll): scroll events --- packages/core/src/components.d.ts | 5 +-- .../core/src/components/content/content.tsx | 15 ------- .../core/src/components/content/readme.md | 42 ------------------- .../infinite-scroll/infinite-scroll.tsx | 3 ++ .../core/src/components/scroll/scroll.tsx | 15 +++++-- .../virtual-scroll/virtual-scroll-utils.tsx | 29 +++++++++---- .../virtual-scroll/virtual-scroll.tsx | 1 - 7 files changed, 36 insertions(+), 74 deletions(-) diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index 29a595e193..faf562e17a 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -759,9 +759,6 @@ declare global { namespace JSXElements { export interface IonContentAttributes extends HTMLAttributes { fullscreen?: boolean; - ionScroll?: Function; - ionScrollEnd?: Function; - ionScrollStart?: Function; } } } @@ -2530,10 +2527,10 @@ declare global { } namespace JSXElements { export interface IonScrollAttributes extends HTMLAttributes { - disabled?: boolean; onionScroll?: ScrollCallback; onionScrollEnd?: ScrollCallback; onionScrollStart?: ScrollCallback; + scrollEvents?: boolean; } } } diff --git a/packages/core/src/components/content/content.tsx b/packages/core/src/components/content/content.tsx index 58914fd51b..59c61ce7a1 100644 --- a/packages/core/src/components/content/content.tsx +++ b/packages/core/src/components/content/content.tsx @@ -25,21 +25,6 @@ export class Content { @Prop({ context: 'config' }) config: Config; @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 * and footers. This effect can easily be seen by setting the toolbar diff --git a/packages/core/src/components/content/readme.md b/packages/core/src/components/content/readme.md index 51c6442b86..0dd8f3cb83 100644 --- a/packages/core/src/components/content/readme.md +++ b/packages/core/src/components/content/readme.md @@ -25,27 +25,6 @@ and footers. This effect can easily be seen by setting the toolbar to transparent. -#### ionScroll - - - -Emitted on every scroll event. - - -#### ionScrollEnd - - - -Emitted when scrolling ends. - - -#### ionScrollStart - - - -Emitted when the scrolling first starts. - - ## Attributes #### fullscreen @@ -57,27 +36,6 @@ and footers. This effect can easily be seen by setting the toolbar 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 #### scrollToBottom() diff --git a/packages/core/src/components/infinite-scroll/infinite-scroll.tsx b/packages/core/src/components/infinite-scroll/infinite-scroll.tsx index bc1f665f28..4641a8f340 100644 --- a/packages/core/src/components/infinite-scroll/infinite-scroll.tsx +++ b/packages/core/src/components/infinite-scroll/infinite-scroll.tsx @@ -227,6 +227,9 @@ export class InfiniteScroll { private enableScrollEvents(shouldListen: boolean) { if (this.scrollEl) { + if (shouldListen) { + this.scrollEl.scrollEvents = true; + } this.enableListener(this, 'ionScroll', shouldListen, this.scrollEl); } } diff --git a/packages/core/src/components/scroll/scroll.tsx b/packages/core/src/components/scroll/scroll.tsx index bb31076b5a..282d438cff 100644 --- a/packages/core/src/components/scroll/scroll.tsx +++ b/packages/core/src/components/scroll/scroll.tsx @@ -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 { GestureController, GestureDelegate } from '../gesture-controller/gesture-controller'; @@ -21,11 +21,10 @@ export class Scroll { @Element() private el: HTMLElement; @Prop({ context: 'config'}) config: Config; + @Prop({ context: 'enableListener'}) enableListener: EventListenerEnable; @Prop({ context: 'dom' }) dom: DomController; @Prop({ context: 'isServer' }) isServer: boolean; - @Prop() disabled = false; - @Prop() onionScrollStart: ScrollCallback; @Prop() onionScroll: ScrollCallback; @Prop() onionScrollEnd: ScrollCallback; @@ -45,6 +44,13 @@ export class Scroll { */ @Event() ionScrollEnd: EventEmitter; + + @Prop() scrollEvents = false; + @Watch('scrollEvents') + scrollChanged(enabled: boolean) { + this.enableListener(this, 'scroll', enabled); + } + componentDidLoad() { if (this.isServer) { return; @@ -53,6 +59,7 @@ export class Scroll { const gestureCtrl = Ionic.gesture = Ionic.gesture || new GestureController(); this.gesture = gestureCtrl.createGesture('scroll', 100, false); this.app = this.el.closest('ion-app') as HTMLIonAppElement; + this.scrollChanged(this.scrollEvents); } componentDidUnload() { @@ -62,7 +69,7 @@ export class Scroll { // Native Scroll ************************* - @Listen('scroll', { passive: true }) + @Listen('scroll', { passive: true, enabled: false }) onNativeScroll() { if (!this.queued) { this.queued = true; diff --git a/packages/core/src/components/virtual-scroll/virtual-scroll-utils.tsx b/packages/core/src/components/virtual-scroll/virtual-scroll-utils.tsx index 0ae5eb1b15..6c9e4d972c 100644 --- a/packages/core/src/components/virtual-scroll/virtual-scroll-utils.tsx +++ b/packages/core/src/components/virtual-scroll/virtual-scroll-utils.tsx @@ -21,10 +21,10 @@ export const enum NodeChange { } export interface Cell { - type: CellType; - value: any; i: number; index: number; + value: any; + type: CellType; height: number; reads: number; visible: boolean; @@ -35,6 +35,7 @@ export interface VirtualNode { top: number; change: NodeChange; d: boolean; + visible: boolean; } const MIN_READS = 2; @@ -88,6 +89,7 @@ export function updateVDom(dom: VirtualNode[], heightIndex: Uint32Array, cells: dom.push({ d: false, cell: cell, + visible: true, change: NodeChange.Cell, top: heightIndex[index], }); @@ -106,8 +108,10 @@ export function doRender( el: HTMLElement, itemRender: ItemRenderFn, dom: VirtualNode[], - updateCellHeight: Function) { + updateCellHeight: Function +) { const children = el.children; + const childrenNu = children.length; let child: HTMLElement; for (let i = 0; i < dom.length; i++) { const node = dom[i]; @@ -115,7 +119,7 @@ export function doRender( // the cell change, the content must be updated if (node.change === NodeChange.Cell) { - if (i < children.length) { + if (i < childrenNu) { child = children[i] as HTMLElement; itemRender(child, cell, i); } else { @@ -132,13 +136,22 @@ export function doRender( if (node.change !== NodeChange.NoChange) { child.style.transform = `translate3d(0,${node.top}px,0)`; } - if (cell.visible) { - child.classList.remove('virtual-loading'); - } else { - child.classList.add('virtual-loading'); + + // update visibility + const visible = cell.visible; + 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) { updateCellHeight(cell, child); + cell.reads--; } } } diff --git a/packages/core/src/components/virtual-scroll/virtual-scroll.tsx b/packages/core/src/components/virtual-scroll/virtual-scroll.tsx index b9214a18b0..b011cd901e 100644 --- a/packages/core/src/components/virtual-scroll/virtual-scroll.tsx +++ b/packages/core/src/components/virtual-scroll/virtual-scroll.tsx @@ -228,7 +228,6 @@ export class VirtualScroll { return; } cell.visible = true; - cell.reads--; if (cell.height !== height) { console.debug(`[${cell.reads}] cell size ${cell.height} -> ${height}`); cell.height = height;