perf(item): reorder is only added to the DOM if needed

I have measured the performance impact of this change, since we use the push change detector strategy, the *ngIf is only evaluated once.

Items wrapped around an element with the ListReorder directive will receive a hidden `<ion-reorder>` in their DOM, but items that are not wrapped (i.e. they CAN NOT be reordered) will not even have the `<ion-reorder>` element in their DOM.

fixes #9065
This commit is contained in:
Manu Mtz.-Almeida
2016-11-08 13:22:12 +01:00
parent ac157c0474
commit dec5a0b35c
5 changed files with 28 additions and 45 deletions

View File

@ -47,7 +47,7 @@ export class ItemReorderGesture {
console.error('ion-reorder does not contain $ionComponent'); console.error('ion-reorder does not contain $ionComponent');
return false; return false;
} }
this.reorderList.reorderPrepare(); this.reorderList._reorderPrepare();
let item = reorderMark.getReorderNode(); let item = reorderMark.getReorderNode();
if (!item) { if (!item) {
@ -63,13 +63,13 @@ export class ItemReorderGesture {
this.lastToIndex = indexForItem(item); this.lastToIndex = indexForItem(item);
this.windowHeight = window.innerHeight - AUTO_SCROLL_MARGIN; this.windowHeight = window.innerHeight - AUTO_SCROLL_MARGIN;
this.lastScrollPosition = this.reorderList.scrollContent(0); this.lastScrollPosition = this.reorderList._scrollContent(0);
this.offset = pointerCoord(ev); this.offset = pointerCoord(ev);
this.offset.y += this.lastScrollPosition; this.offset.y += this.lastScrollPosition;
item.classList.add(ITEM_REORDER_ACTIVE); item.classList.add(ITEM_REORDER_ACTIVE);
this.reorderList.reorderStart(); this.reorderList._reorderStart();
return true; return true;
} }
@ -97,7 +97,7 @@ export class ItemReorderGesture {
this.lastToIndex = toIndex; this.lastToIndex = toIndex;
this.lastYcoord = posY; this.lastYcoord = posY;
this.emptyZone = false; this.emptyZone = false;
this.reorderList.reorderMove(fromIndex, toIndex, this.selectedItemHeight); this.reorderList._reorderMove(fromIndex, toIndex, this.selectedItemHeight);
} }
} else { } else {
this.emptyZone = true; this.emptyZone = true;
@ -133,7 +133,7 @@ export class ItemReorderGesture {
} else { } else {
reorderInactive(); reorderInactive();
} }
this.reorderList.reorderEmit(fromIndex, toIndex); this.reorderList._reorderEmit(fromIndex, toIndex);
} }
private itemForCoord(coord: PointerCoordinates): HTMLElement { private itemForCoord(coord: PointerCoordinates): HTMLElement {
@ -142,9 +142,9 @@ export class ItemReorderGesture {
private scroll(posY: number): number { private scroll(posY: number): number {
if (posY < AUTO_SCROLL_MARGIN) { if (posY < AUTO_SCROLL_MARGIN) {
this.lastScrollPosition = this.reorderList.scrollContent(-SCROLL_JUMP); this.lastScrollPosition = this.reorderList._scrollContent(-SCROLL_JUMP);
} else if (posY > this.windowHeight) { } else if (posY > this.windowHeight) {
this.lastScrollPosition = this.reorderList.scrollContent(SCROLL_JUMP); this.lastScrollPosition = this.reorderList._scrollContent(SCROLL_JUMP);
} }
return this.lastScrollPosition; return this.lastScrollPosition;
} }

View File

@ -133,19 +133,10 @@ export interface ReorderIndexes {
}) })
export class ItemReorder { export class ItemReorder {
/** @private */
_enableReorder: boolean = false; _enableReorder: boolean = false;
/** @private */
_visibleReorder: boolean = false; _visibleReorder: boolean = false;
/** @private */
_reorderGesture: ItemReorderGesture; _reorderGesture: ItemReorderGesture;
/** @private */
_lastToIndex: number = -1; _lastToIndex: number = -1;
/** @private */
_element: HTMLElement; _element: HTMLElement;
/** /**
@ -196,10 +187,7 @@ export class ItemReorder {
} }
} }
/** _reorderPrepare() {
* @private
*/
reorderPrepare() {
let ele = this._element; let ele = this._element;
let children: any = ele.children; let children: any = ele.children;
for (let i = 0, ilen = children.length; i < ilen; i++) { for (let i = 0, ilen = children.length; i < ilen; i++) {
@ -209,18 +197,12 @@ export class ItemReorder {
} }
} }
/** _reorderStart() {
* @private
*/
reorderStart() {
this.setElementClass('reorder-list-active', true); this.setElementClass('reorder-list-active', true);
} }
/** _reorderEmit(fromIndex: number, toIndex: number) {
* @private this._reorderReset();
*/
reorderEmit(fromIndex: number, toIndex: number) {
this.reorderReset();
if (fromIndex !== toIndex) { if (fromIndex !== toIndex) {
this._zone.run(() => { this._zone.run(() => {
this.ionItemReorder.emit({ this.ionItemReorder.emit({
@ -231,10 +213,7 @@ export class ItemReorder {
} }
} }
/** _scrollContent(scroll: number) {
* @private
*/
scrollContent(scroll: number) {
let scrollTop = this._content.getScrollTop() + scroll; let scrollTop = this._content.getScrollTop() + scroll;
if (scroll !== 0) { if (scroll !== 0) {
this._content.scrollTo(0, scrollTop, 0); this._content.scrollTo(0, scrollTop, 0);
@ -242,10 +221,7 @@ export class ItemReorder {
return scrollTop; return scrollTop;
} }
/** _reorderReset() {
* @private
*/
reorderReset() {
let children = this._element.children; let children = this._element.children;
let len = children.length; let len = children.length;
@ -257,10 +233,7 @@ export class ItemReorder {
this._lastToIndex = -1; this._lastToIndex = -1;
} }
/** _reorderMove(fromIndex: number, toIndex: number, itemHeight: number) {
* @private
*/
reorderMove(fromIndex: number, toIndex: number, itemHeight: number) {
if (this._lastToIndex === -1) { if (this._lastToIndex === -1) {
this._lastToIndex = fromIndex; this._lastToIndex = fromIndex;
} }

View File

@ -10,6 +10,7 @@ const DRAG_THRESHOLD = 10;
const MAX_ATTACK_ANGLE = 20; const MAX_ATTACK_ANGLE = 20;
export class ItemSlidingGesture extends PanGesture { export class ItemSlidingGesture extends PanGesture {
private preSelectedContainer: ItemSliding = null; private preSelectedContainer: ItemSliding = null;
private selectedContainer: ItemSliding = null; private selectedContainer: ItemSliding = null;
private openContainer: ItemSliding = null; private openContainer: ItemSliding = null;

View File

@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, ContentChild, ContentChildren, Directive, ElementRef, Input, QueryList, Renderer, ViewChild, ViewEncapsulation } from '@angular/core'; import { ChangeDetectionStrategy, Component, ContentChild, ContentChildren, Directive, ElementRef, Input, QueryList, Renderer, Optional, ViewChild, ViewEncapsulation } from '@angular/core';
import { Button } from '../button/button'; import { Button } from '../button/button';
import { Config } from '../../config/config'; import { Config } from '../../config/config';
@ -6,6 +6,7 @@ import { Form } from '../../util/form';
import { Icon } from '../icon/icon'; import { Icon } from '../icon/icon';
import { Ion } from '../ion'; import { Ion } from '../ion';
import { Label } from '../label/label'; import { Label } from '../label/label';
import { ItemReorder } from './item-reorder';
/** /**
@ -283,7 +284,7 @@ import { Label } from '../label/label';
'<ng-content select="ion-select,ion-input,ion-textarea,ion-datetime,ion-range,[item-content]"></ng-content>' + '<ng-content select="ion-select,ion-input,ion-textarea,ion-datetime,ion-range,[item-content]"></ng-content>' +
'</div>' + '</div>' +
'<ng-content select="[item-right],ion-radio,ion-toggle"></ng-content>' + '<ng-content select="[item-right],ion-radio,ion-toggle"></ng-content>' +
'<ion-reorder></ion-reorder>' + '<ion-reorder *ngIf="_shouldHaveReorder"></ion-reorder>' +
'</div>' + '</div>' +
'<div class="button-effect"></div>', '<div class="button-effect"></div>',
host: { host: {
@ -297,6 +298,7 @@ export class Item extends Ion {
_inputs: Array<string> = []; _inputs: Array<string> = [];
_label: Label; _label: Label;
_viewLabel: boolean = true; _viewLabel: boolean = true;
_shouldHaveReorder: boolean = false;
/** /**
* @private * @private
@ -324,9 +326,15 @@ export class Item extends Ion {
this._setMode('item', val); this._setMode('item', val);
} }
constructor(form: Form, config: Config, elementRef: ElementRef, renderer: Renderer) { constructor(
form: Form,
config: Config,
elementRef: ElementRef,
renderer: Renderer,
@Optional() reorder: ItemReorder
) {
super(config, elementRef, renderer); super(config, elementRef, renderer);
this._shouldHaveReorder = !!reorder;
this.mode = config.get('mode'); this.mode = config.get('mode');
this.id = form.nextId().toString(); this.id = form.nextId().toString();
} }

View File

@ -24,6 +24,7 @@ import { TransitionController } from '../transitions/transition-controller';
* This class is for internal use only. It is not exported publicly. * This class is for internal use only. It is not exported publicly.
*/ */
export class NavControllerBase extends Ion implements NavController { export class NavControllerBase extends Ion implements NavController {
_children: any[] = []; _children: any[] = [];
_ids: number = -1; _ids: number = -1;
_init = false; _init = false;