perf(toggle): events are not zoned

This commit is contained in:
Manuel Mtz-Almeida
2017-04-07 19:59:47 +02:00
parent c792ab69ae
commit bda624f870
5 changed files with 57 additions and 33 deletions

View File

@ -1,6 +1,6 @@
import { Toggle } from '../toggle'; 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'; import { commonInputTest, BOOLEAN_CORPUS } from '../../../util/input-tester';
describe('Toggle', () => { describe('Toggle', () => {
@ -16,7 +16,8 @@ describe('Toggle', () => {
const haptic = mockHaptic(); const haptic = mockHaptic();
const cd = mockChangeDetectorRef(); const cd = mockChangeDetectorRef();
const gesture = mockGestureController(); 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, { commonInputTest(toggle, {
defaultValue: false, defaultValue: false,

View File

@ -20,7 +20,7 @@ export class ToggleGesture extends PanGesture {
plt, plt,
toggle.getNativeElement(), { toggle.getNativeElement(), {
threshold: 0, threshold: 0,
zone: true, zone: false,
domController: domCtrl, domController: domCtrl,
gesture: gestureCtrl.createGesture({ gesture: gestureCtrl.createGesture({
name: GESTURE_TOGGLE, name: GESTURE_TOGGLE,

View File

@ -61,11 +61,11 @@ $toggle-md-item-right-padding: 12px ($item-md-padding-right / 2) 12px
.toggle-md { .toggle-md {
position: relative; position: relative;
padding: $toggle-md-padding;
width: $toggle-md-track-width; width: $toggle-md-track-width;
height: $toggle-md-track-height; height: $toggle-md-track-height;
padding: $toggle-md-padding;
box-sizing: content-box; 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-duration: $toggle-md-transition-duration;
transition-property: transform, background-color; transition-property: transform, background-color;
will-change: transform, background-color;
contain: strict;
} }

View File

@ -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 { NG_VALUE_ACCESSOR } from '@angular/forms';
import { Config } from '../../config/config'; import { Config } from '../../config/config';
@ -13,7 +13,6 @@ import { KEY_ENTER, KEY_SPACE } from '../../platform/key';
import { Platform } from '../../platform/platform'; import { Platform } from '../../platform/platform';
import { ToggleGesture } from './toggle-gesture'; import { ToggleGesture } from './toggle-gesture';
export const TOGGLE_VALUE_ACCESSOR: any = { export const TOGGLE_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => Toggle), useExisting: forwardRef(() => Toggle),
@ -109,7 +108,8 @@ export class Toggle extends BaseInput<boolean> implements IonicTapInput, AfterVi
@Optional() item: Item, @Optional() item: Item,
private _gestureCtrl: GestureController, private _gestureCtrl: GestureController,
private _domCtrl: DomController, private _domCtrl: DomController,
private _cd: ChangeDetectorRef private _cd: ChangeDetectorRef,
private _zone: NgZone,
) { ) {
super(config, elementRef, renderer, 'toggle', false, form, item, null); super(config, elementRef, renderer, 'toggle', false, form, item, null);
} }
@ -142,9 +142,11 @@ export class Toggle extends BaseInput<boolean> implements IonicTapInput, AfterVi
assert(startX, 'startX must be valid'); assert(startX, 'startX must be valid');
console.debug('toggle, _onDragStart', startX); console.debug('toggle, _onDragStart', startX);
this._startX = startX; this._zone.run(() => {
this._fireFocus(); this._startX = startX;
this._activated = true; this._fireFocus();
this._activated = true;
});
} }
/** /**
@ -156,22 +158,32 @@ export class Toggle extends BaseInput<boolean> implements IonicTapInput, AfterVi
return; return;
} }
console.debug('toggle, _onDragMove', currentX); let dirty = false;
let value: boolean;
let activated: boolean;
if (this._value) { if (this._value) {
if (currentX + 15 < this._startX) { if (currentX + 15 < this._startX) {
this.value = false; dirty = true;
this._haptic.selection(); value = false;
this._startX = currentX; activated = true;
this._activated = true;
} }
} else if (currentX - 15 > this._startX) { } else if (currentX - 15 > this._startX) {
this.value = true; dirty = true;
this._haptic.selection(); value = true;
this._startX = currentX; activated = (currentX < this._startX + 5);
this._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<boolean> implements IonicTapInput, AfterVi
} }
console.debug('toggle, _onDragEnd', endX); console.debug('toggle, _onDragEnd', endX);
if (this._value) { this._zone.run(() => {
if (this._startX + 4 > endX) { if (this._value) {
this.value = false; if (this._startX + 4 > endX) {
this.value = false;
this._haptic.selection();
}
} else if (this._startX - 4 < endX) {
this.value = true;
this._haptic.selection(); this._haptic.selection();
} }
} else if (this._startX - 4 < endX) { this._activated = false;
this.value = true; this._fireBlur();
this._haptic.selection(); this._startX = null;
} });
this._activated = false;
this._fireBlur();
this._startX = null;
} }
/** /**

View File

@ -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 { ControlValueAccessor } from '@angular/forms';
import { NgControl } from '@angular/forms'; import { NgControl } from '@angular/forms';
@ -130,6 +130,8 @@ export class BaseInput<T> extends Ion implements CommonInput<T> {
* @hidden * @hidden
*/ */
_writeValue(val: any): boolean { _writeValue(val: any): boolean {
assert(NgZone.isInAngularZone(), 'callback should be zoned');
if (isUndefined(val)) { if (isUndefined(val)) {
return false; return false;
} }
@ -154,7 +156,10 @@ export class BaseInput<T> extends Ion implements CommonInput<T> {
*/ */
_fireIonChange() { _fireIonChange() {
if (this._init) { if (this._init) {
this._debouncer.debounce(() => this.ionChange.emit(this)); this._debouncer.debounce(() => {
assert(NgZone.isInAngularZone(), 'callback should be zoned');
this.ionChange.emit(this);
});
} }
} }