如何正确处理 click/touch 事件中的混合设备?
How to handle hybrid devices in click/touch events properly?
我正在尝试了解在绑定触摸和点击事件时如何使用混合设备,但我找不到任何实际可行的解决方案(我没有混合设备所以我不能直接测试,但由于失败的尝试甚至不能在普通设备上工作,我认为它们也不能在混合设备上工作。
问题在于,在混合设备上,您必须同时覆盖触摸和点击事件,而不触发两次功能。因此,如果您查看我失败的尝试(2 和 3),您可以看到我同时绑定了 touchend
和 click
,但似乎存在某种语法错误或其他原因,因为这会导致 none 实际触发的事件。
第一个解决方案工作正常,但那是我只使用一种或另一种事件触发类型的时候。
到目前为止我尝试过的:
1 - 适用于触摸设备和点击设备:
_renderer.listenGlobal('document', 'ontouchstart' in window ? 'touchend' : 'click', (e) => {
console.log('works');
});
2 - 在触摸或点击设备上均不触发:
_renderer.listenGlobal('document', 'touchend click', (e) => {
console.log('works');
e.stopPropagation();
});
3 - 在触摸或点击设备上均不触发:
_renderer.listenGlobal('document', 'touchend, click', (e) => {
console.log('works');
e.stopPropagation();
});
如您所见,第一个示例涵盖了 2/3 的设备类型,而其他的涵盖了 0。
如何确保我的功能在每台设备上都能正常 运行?
只需在您的组件上添加 (tap) 指令而不是 (click) 指令,并将 hammerjs 添加到您的 index.html 文件。
Angular 2 会为您完成所有工作。
示例:
<my-component (tap)="doSomething()"></my-component>
在您的 index.html 添加:
<script src="hammer.min.js"></script>
获取hammerjs
npm install hammerjs --save
有了这个,点击和点击就可以正常工作了。
如果你想对点击有更多的控制,或者你想在运行时将事件绑定到你的元素,试试这样的事情。
_hammerEvents: HammerManager;
public bindTapEvent(element: ElementRef):void{
this._hammerEvents = new Hammer(element.nativeElement);
this._hammerEvents.on("tap", (event:any) => { /* do something */});
}
您可以使用主题并去抖几毫秒,这样您就只有一个事件,如下所示:
import {Component, Renderer} from '@angular/core'
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/debounceTime';
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
`,
})
export class App {
name = 'Angular2';
subject = new Subject();
constructor(renderer: Renderer) {
renderer.listenGlobal('document', 'touchend', (e) => {
console.log('touchend');
this.subject.next(e);
});
renderer.listenGlobal('document', 'click', (e) => {
console.log('click');
this.subject.next(e);
});
this.subject.debounceTime(100).subscribe(event => {
console.log(event); //do stuff here
})
}
}
所以当你使用混合设备时,你会得到这个:
触发了两个事件,但您只能在 Observable 上获得一个。
你可以玩这个plunker
我正在尝试了解在绑定触摸和点击事件时如何使用混合设备,但我找不到任何实际可行的解决方案(我没有混合设备所以我不能直接测试,但由于失败的尝试甚至不能在普通设备上工作,我认为它们也不能在混合设备上工作。
问题在于,在混合设备上,您必须同时覆盖触摸和点击事件,而不触发两次功能。因此,如果您查看我失败的尝试(2 和 3),您可以看到我同时绑定了 touchend
和 click
,但似乎存在某种语法错误或其他原因,因为这会导致 none 实际触发的事件。
第一个解决方案工作正常,但那是我只使用一种或另一种事件触发类型的时候。
到目前为止我尝试过的:
1 - 适用于触摸设备和点击设备:
_renderer.listenGlobal('document', 'ontouchstart' in window ? 'touchend' : 'click', (e) => {
console.log('works');
});
2 - 在触摸或点击设备上均不触发:
_renderer.listenGlobal('document', 'touchend click', (e) => {
console.log('works');
e.stopPropagation();
});
3 - 在触摸或点击设备上均不触发:
_renderer.listenGlobal('document', 'touchend, click', (e) => {
console.log('works');
e.stopPropagation();
});
如您所见,第一个示例涵盖了 2/3 的设备类型,而其他的涵盖了 0。
如何确保我的功能在每台设备上都能正常 运行?
只需在您的组件上添加 (tap) 指令而不是 (click) 指令,并将 hammerjs 添加到您的 index.html 文件。
Angular 2 会为您完成所有工作。
示例:
<my-component (tap)="doSomething()"></my-component>
在您的 index.html 添加:
<script src="hammer.min.js"></script>
获取hammerjs
npm install hammerjs --save
有了这个,点击和点击就可以正常工作了。 如果你想对点击有更多的控制,或者你想在运行时将事件绑定到你的元素,试试这样的事情。
_hammerEvents: HammerManager;
public bindTapEvent(element: ElementRef):void{
this._hammerEvents = new Hammer(element.nativeElement);
this._hammerEvents.on("tap", (event:any) => { /* do something */});
}
您可以使用主题并去抖几毫秒,这样您就只有一个事件,如下所示:
import {Component, Renderer} from '@angular/core'
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/debounceTime';
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
</div>
`,
})
export class App {
name = 'Angular2';
subject = new Subject();
constructor(renderer: Renderer) {
renderer.listenGlobal('document', 'touchend', (e) => {
console.log('touchend');
this.subject.next(e);
});
renderer.listenGlobal('document', 'click', (e) => {
console.log('click');
this.subject.next(e);
});
this.subject.debounceTime(100).subscribe(event => {
console.log(event); //do stuff here
})
}
}
所以当你使用混合设备时,你会得到这个:
触发了两个事件,但您只能在 Observable 上获得一个。
你可以玩这个plunker