如何正确处理 click/touch 事件中的混合设备?

How to handle hybrid devices in click/touch events properly?

我正在尝试了解在绑定触摸和点击事件时如何使用混合设备,但我找不到任何实际可行的解决方案(我没有混合设备所以我不能直接测试,但由于失败的尝试甚至不能在普通设备上工作,我认为它们也不能在混合设备上工作。

问题在于,在混合设备上,您必须同时覆盖触摸和点击事件,而不触发两次功能。因此,如果您查看我失败的尝试(2 和 3),您可以看到我同时绑定了 touchendclick,但似乎存在某种语法错误或其他原因,因为这会导致 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