移动开发与PC开发大相径庭,PC上最多的是鼠标点击事件,但是手机上面的手势事件却又很多,最常见的开发问题是处理父控件与子控件事件冲突问题,这就要我们十分了解手势了。ionic使用的是angular的库,用hammer来解决移动端的屏幕手势。
1、angular处理事件源码:
这里直接贴上angular源码地址:angular源码之hammer_gestures <这里方便它更新后的修改> 这里又贴上该地址的源码以便说明:
代码语言:javascript复制/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {Inject, Injectable, InjectionToken} from '@angular/core';
import {DOCUMENT} from '../dom_tokens';
import {EventManagerPlugin} from './event_manager';
const EVENT_NAMES = {
// pan
'pan': true,
'panstart': true,
'panmove': true,
'panend': true,
'pancancel': true,
'panleft': true,
'panright': true,
'panup': true,
'pandown': true,
// pinch
'pinch': true,
'pinchstart': true,
'pinchmove': true,
'pinchend': true,
'pinchcancel': true,
'pinchin': true,
'pinchout': true,
// press
'press': true,
'pressup': true,
// rotate
'rotate': true,
'rotatestart': true,
'rotatemove': true,
'rotateend': true,
'rotatecancel': true,
// swipe
'swipe': true,
'swipeleft': true,
'swiperight': true,
'swipeup': true,
'swipedown': true,
// tap
'tap': true,
};
/**
* A DI token that you can use to provide{@link HammerGestureConfig} to Angular. Use it to configure
* Hammer gestures.
*
* @experimental
*/
export const HAMMER_GESTURE_CONFIG = new InjectionToken<HammerGestureConfig>('HammerGestureConfig');
export interface HammerInstance {
on(eventName: string, callback?: Function): void;
off(eventName: string, callback?: Function): void;
}
/**
* @experimental
*/
@Injectable()
export class HammerGestureConfig {
events: string[] = [];
overrides: {[key: string]: Object} = {};
buildHammer(element: HTMLElement): HammerInstance {
const mc = new Hammer(element);
mc.get('pinch').set({enable: true});
mc.get('rotate').set({enable: true});
for (const eventName in this.overrides) {
mc.get(eventName).set(this.overrides[eventName]);
}
return mc;
}
}
@Injectable()
export class HammerGesturesPlugin extends EventManagerPlugin {
constructor(
@Inject(DOCUMENT) doc: any,
@Inject(HAMMER_GESTURE_CONFIG) private _config: HammerGestureConfig) {
super(doc);
}
supports(eventName: string): boolean {
if (!EVENT_NAMES.hasOwnProperty(eventName.toLowerCase()) && !this.isCustomEvent(eventName)) {
return false;
}
if (!(window as any).Hammer) {
throw new Error(`Hammer.js is not loaded, can not bind ${eventName} event`);
}
return true;
}
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function {
const zone = this.manager.getZone();
eventName = eventName.toLowerCase();
return zone.runOutsideAngular(() => {
// Creating the manager bind events, must be done outside of angular
const mc = this._config.buildHammer(element);
const callback = function(eventObj: HammerInput) {
zone.runGuarded(function() { handler(eventObj); });
};
mc.on(eventName, callback);
return () => mc.off(eventName, callback);
});
}
isCustomEvent(eventName: string): boolean { return this._config.events.indexOf(eventName) > -1; }
}
源码上的手势都可以这样来使用:
代码语言:javascript复制// html:
<ion-item (xxx)=method($event)></ion-item>
// ts:
method(event){ //TODO ideal }
即通过dom绑定来绑定一个处理事件的方法。
源码中跟我们划分好了有pan【随手指移动跟随事件】、pinch【双手指捏合事件】、press【长按事件】、rotate【手势翻转事件】、swipe【手指迅速滑动事件】、tap【短时间触摸事件】
这里说明各大事件是使用场景:pinch事件是在图片放大缩小的时候,拇指与食指进行缩放操作就可以使用pinch事件来实现,pan事件与swipe事件可以用来处理左右滑动等问题,rotate可以使用来实现使用操作杆等3D手势,tap可以代替点击click事件,press就不用详细说明了,大家都懂。
2、实际运用手势来处理事件冲突
错误写法1
代码语言:javascript复制//html
<ion-item (tap)=parentClick($event)>
<button ion-button block (click)="childClick($event)">子控件点击</button>
</ion-item>
此时父控件手势完全遮盖住了子控件,造成button点击无效。
错误写法2
代码语言:javascript复制//html
<ion-item (tap)=parentClick($event)>
<button ion-button block (tap)="childClick($event)">子控件点击</button>
</ion-item>
//html
<ion-item (click)=parentClick($event)>
<button ion-button block (click)="childClick($event)">子控件点击</button>
</ion-item>
这是我们常见的写法,两个同时用click或者tap来完成点击事件的处理,在实际操作中造成事件冒泡,点击button,两个方法同时运行。
正确写法
代码语言:javascript复制//html
<ion-item (click)=parentClick($event)>
<button ion-button block (tap)="childClick($event)">子控件点击</button>
</ion-item>
由于错误写法1我们了解到,tap事件是触摸事件,并不是点击事件,在触发的时候会隔离事件冒泡,虽然不能一起使用,但是可以在click事件上阻止click触发,所以我们在子控件上使用tap,父控件上使用click,这样可以让我们的时间冒泡问题得以解决。
附上angular语法防止事件冒泡的文章: angular4 防止事件冒泡
timg.jpeg