From bda624f8708d934d190090bce025f2021ca7fcb7 Mon Sep 17 00:00:00 2001 From: Manuel Mtz-Almeida Date: Fri, 7 Apr 2017 19:59:47 +0200 Subject: [PATCH] perf(toggle): events are not zoned --- src/components/toggle/test/toggle.spec.ts | 5 +- src/components/toggle/toggle-gesture.ts | 2 +- src/components/toggle/toggle.md.scss | 8 ++- src/components/toggle/toggle.ts | 66 ++++++++++++++--------- src/util/base-input.ts | 9 +++- 5 files changed, 57 insertions(+), 33 deletions(-) diff --git a/src/components/toggle/test/toggle.spec.ts b/src/components/toggle/test/toggle.spec.ts index 85387eb1df..ee27d02c75 100644 --- a/src/components/toggle/test/toggle.spec.ts +++ b/src/components/toggle/test/toggle.spec.ts @@ -1,6 +1,6 @@ import { Toggle } from '../toggle'; -import { mockConfig, mockPlatform, mockHaptic, mockElementRef, mockGestureController, mockRenderer, mockItem, mockForm, mockChangeDetectorRef } from '../../../util/mock-providers'; +import { mockConfig, mockPlatform, mockHaptic, mockElementRef, mockGestureController, mockRenderer, mockItem, mockForm, mockChangeDetectorRef, mockZone } from '../../../util/mock-providers'; import { commonInputTest, BOOLEAN_CORPUS } from '../../../util/input-tester'; describe('Toggle', () => { @@ -16,7 +16,8 @@ describe('Toggle', () => { const haptic = mockHaptic(); const cd = mockChangeDetectorRef(); const gesture = mockGestureController(); - const toggle = new Toggle(form, config, platform, elementRef, renderer, haptic, item, gesture, null, cd); + const zone = mockZone(); + const toggle = new Toggle(form, config, platform, elementRef, renderer, haptic, item, gesture, null, cd, zone); commonInputTest(toggle, { defaultValue: false, diff --git a/src/components/toggle/toggle-gesture.ts b/src/components/toggle/toggle-gesture.ts index 245e839aac..8b97d4b8ca 100644 --- a/src/components/toggle/toggle-gesture.ts +++ b/src/components/toggle/toggle-gesture.ts @@ -20,7 +20,7 @@ export class ToggleGesture extends PanGesture { plt, toggle.getNativeElement(), { threshold: 0, - zone: true, + zone: false, domController: domCtrl, gesture: gestureCtrl.createGesture({ name: GESTURE_TOGGLE, diff --git a/src/components/toggle/toggle.md.scss b/src/components/toggle/toggle.md.scss index 2ee71ea077..e4885d40bb 100644 --- a/src/components/toggle/toggle.md.scss +++ b/src/components/toggle/toggle.md.scss @@ -61,11 +61,11 @@ $toggle-md-item-right-padding: 12px ($item-md-padding-right / 2) 12px .toggle-md { position: relative; + padding: $toggle-md-padding; + width: $toggle-md-track-width; height: $toggle-md-track-height; - padding: $toggle-md-padding; - box-sizing: content-box; } @@ -107,6 +107,10 @@ $toggle-md-item-right-padding: 12px ($item-md-padding-right / 2) 12px transition-duration: $toggle-md-transition-duration; transition-property: transform, background-color; + + will-change: transform, background-color; + + contain: strict; } diff --git a/src/components/toggle/toggle.ts b/src/components/toggle/toggle.ts index 44a7b10ab3..d941e130cd 100644 --- a/src/components/toggle/toggle.ts +++ b/src/components/toggle/toggle.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, forwardRef, HostListener, Input, OnDestroy, Optional, Renderer, ViewEncapsulation } from '@angular/core'; +import { NgZone, AfterViewInit, ChangeDetectorRef, Component, ElementRef, forwardRef, HostListener, Input, OnDestroy, Optional, Renderer, ViewEncapsulation } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { Config } from '../../config/config'; @@ -13,7 +13,6 @@ import { KEY_ENTER, KEY_SPACE } from '../../platform/key'; import { Platform } from '../../platform/platform'; import { ToggleGesture } from './toggle-gesture'; - export const TOGGLE_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => Toggle), @@ -109,7 +108,8 @@ export class Toggle extends BaseInput implements IonicTapInput, AfterVi @Optional() item: Item, private _gestureCtrl: GestureController, private _domCtrl: DomController, - private _cd: ChangeDetectorRef + private _cd: ChangeDetectorRef, + private _zone: NgZone, ) { super(config, elementRef, renderer, 'toggle', false, form, item, null); } @@ -142,9 +142,11 @@ export class Toggle extends BaseInput implements IonicTapInput, AfterVi assert(startX, 'startX must be valid'); console.debug('toggle, _onDragStart', startX); - this._startX = startX; - this._fireFocus(); - this._activated = true; + this._zone.run(() => { + this._startX = startX; + this._fireFocus(); + this._activated = true; + }); } /** @@ -156,22 +158,32 @@ export class Toggle extends BaseInput implements IonicTapInput, AfterVi return; } - console.debug('toggle, _onDragMove', currentX); + let dirty = false; + let value: boolean; + let activated: boolean; if (this._value) { if (currentX + 15 < this._startX) { - this.value = false; - this._haptic.selection(); - this._startX = currentX; - this._activated = true; + dirty = true; + value = false; + activated = true; } } else if (currentX - 15 > this._startX) { - this.value = true; - this._haptic.selection(); - this._startX = currentX; - this._activated = (currentX < this._startX + 5); + dirty = true; + value = true; + activated = (currentX < this._startX + 5); } + + if (dirty) { + this._zone.run(() => { + this.value = value; + this._startX = currentX; + this._activated = activated; + this._haptic.selection(); + }); + } + } /** @@ -184,20 +196,22 @@ export class Toggle extends BaseInput implements IonicTapInput, AfterVi } console.debug('toggle, _onDragEnd', endX); - if (this._value) { - if (this._startX + 4 > endX) { - this.value = false; + this._zone.run(() => { + if (this._value) { + if (this._startX + 4 > endX) { + this.value = false; + this._haptic.selection(); + } + + } else if (this._startX - 4 < endX) { + this.value = true; this._haptic.selection(); } - } else if (this._startX - 4 < endX) { - this.value = true; - this._haptic.selection(); - } - - this._activated = false; - this._fireBlur(); - this._startX = null; + this._activated = false; + this._fireBlur(); + this._startX = null; + }); } /** diff --git a/src/util/base-input.ts b/src/util/base-input.ts index 4866e60251..1e60aaf014 100644 --- a/src/util/base-input.ts +++ b/src/util/base-input.ts @@ -1,4 +1,4 @@ -import { ElementRef, EventEmitter, Input, Output, Renderer } from '@angular/core'; +import { ElementRef, EventEmitter, Input, NgZone, Output, Renderer } from '@angular/core'; import { ControlValueAccessor } from '@angular/forms'; import { NgControl } from '@angular/forms'; @@ -130,6 +130,8 @@ export class BaseInput extends Ion implements CommonInput { * @hidden */ _writeValue(val: any): boolean { + assert(NgZone.isInAngularZone(), 'callback should be zoned'); + if (isUndefined(val)) { return false; } @@ -154,7 +156,10 @@ export class BaseInput extends Ion implements CommonInput { */ _fireIonChange() { if (this._init) { - this._debouncer.debounce(() => this.ionChange.emit(this)); + this._debouncer.debounce(() => { + assert(NgZone.isInAngularZone(), 'callback should be zoned'); + this.ionChange.emit(this); + }); } }