Как правильно обрабатывать гибридные устройства в событиях щелчка / касания?

#javascript #angular #click #touch

#javascript #angular #нажмите #коснитесь

Вопрос:

Я пытаюсь выяснить, как работать с гибридными устройствами, когда дело доходит до привязки событий касания и нажатия, но я не могу найти никакого решения, которое на самом деле работает (у меня нет гибридного устройства, поэтому я не могу тестировать напрямую, но поскольку неудачные попытки не работают даже на обычных устройствах, я не могу найти какое-либо решение).предположим, что они также не работают на гибридном устройстве).

Проблема в том, что на гибридном устройстве вы должны охватывать как события касания, так и нажатия, не вызывая функции дважды. Итак, если вы посмотрите на мои неудачные попытки (2 и 3), вы можете увидеть, что я привязываюсь к обоим touchend и click , но, похоже, есть какая-то синтаксическая ошибка или что-то в этом роде, потому что это не приводит к фактическому запуску ни одного из событий.

Первое решение работает нормально, но это когда я просто использую один или другой из типов запуска событий.

Что я пробовал до сих пор:

1 — Работает на сенсорных устройствах и устройствах щелчка:

 _renderer.listenGlobal('document', 'ontouchstart' in window ? 'touchend' : 'click', (e) => {

  console.log('works');  
});
  

2 — Не срабатывает ни на устройствах touch, ни на устройствах click:

 _renderer.listenGlobal('document', 'touchend click', (e) => {

  console.log('works');

  e.stopPropagation(); 
});
  

3 — Не срабатывает ни на устройствах touch, ни на устройствах click:

 _renderer.listenGlobal('document', 'touchend, click', (e) => {

  console.log('works');  

  e.stopPropagation();
});
  

Как вы можете видеть, первый пример охватывает 2/3 типов устройств, в то время как другие охватывают 0.

Как я могу убедиться, что мои функции будут работать правильно на каждом устройстве?

Ответ №1:

Вы можете использовать тему и отменить ее на пару миллисекунд, чтобы у вас было только одно событие, что-то вроде этого:

 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
    })
  }
}
  

Итак, когда вы используете гибридные устройства, вы получите это:
введите описание изображения здесь

Были запущены два события, но вы получаете только одно на своем наблюдаемом.

Вы можете поиграть с этим плунжером

Комментарии:

1. Я заинтригован, я проверю это более тщательно.

Ответ №2:

Просто добавьте директиву (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 */});
}
  

Комментарии:

1. Можете ли вы объяснить немного подробнее, зачем мне нужен hammerjs?

2. @Chrillewoodz В Angular 2 уже есть директива (tap), которая была предоставлена для этих случаев, эта директива реагирует на событие нажатия (ontouchstart, touchend) и будет работать с событиями нажатия. Под капотом Angular 2 проверит, был ли загружен hammerjs.

3. Знаете ли вы, как привязать нажатие к документу? Я получаю сообщение об ошибке, в котором говорится, что оно не реализовано

4. Спасибо @dlcardozo. Это работает как шарм. Я тестировал на настольных компьютерах, телефонах adnroid, а также на iPad с iOS 12.

5. Это должен быть правильный ответ. Отлично работает для Angular и было недостающим знанием, в котором я нуждался.