Ionic 4双击触发事件失效求助:双击跳转详情而非执行收藏
Problem
I've set up HammerJS and a custom DoubleTapDirective to handle double-tap events in my Ionic 4 app, aiming to let users double-tap feed posts to add them to favorites. However, double-tapping a post immediately navigates to the post details page via [routerLink], and my doSomething() method (which shows a "Added to favorites." toast) never runs.
Here's my relevant code:
Tab4.html
<div (doubleTap)="doSomething()" id="post" *ngIf="posts" > <ion-card *ngFor="let post of posts" [routerLink]="['/tabs/details-feed/', post.postID]"> <div id="profileImage" > <img id="profileImageIn" [src]="post.profileImage"> </div> <div id="userName" ><h6>{{post.username}}</h6></div> <img [src]="post.image"> </ion-card> </div>
Tab4.ts
import { ToastController } from '@ionic/angular'; constructor( private aff: AngularFireFunctions, public toastController: ToastController ) {} async doSomething() { const toast = await this.toastController.create({ message: 'Added to favorites.', duration: 2000 }); toast.present(); }
Root Cause
The core issue is that the [routerLink] directive responds to the native click event, which fires before your custom doubleTap event. Even though you're listening for double-taps, the single tap that triggers router navigation gets processed first, cutting off your double-tap logic.
Solutions
Solution 1: Prevent Event Propagation in Your DoubleTap Directive
Modify your DoubleTapDirective to stop the event from propagating when a double-tap is detected. This blocks the router link's default click behavior from executing after the double-tap.
Update your directive's tap handler:
import { Directive, Output, EventEmitter, HostListener } from '@angular/core'; @Directive({ selector: '[doubleTap]' }) export class DoubleTapDirective { @Output() doubleTap = new EventEmitter<void>(); @Output() tripleTap = new EventEmitter<void>(); private tapCount = 0; @HostListener('tap', ['$event']) onTap(event: any) { this.tapCount++; setTimeout(() => { if (this.tapCount === 2) { this.doubleTap.emit(); // Block event propagation to stop routerLink from triggering event.preventDefault(); event.stopPropagation(); } else if (this.tapCount === 3) { this.tripleTap.emit(); event.preventDefault(); event.stopPropagation(); } this.tapCount = 0; }, 300); // Adjust this interval to match your desired double-tap speed } }
Solution 2: Handle Clicks Manually (Separate Single/Double Tap Logic)
Instead of using [routerLink], handle all clicks on the post card manually. This lets you explicitly distinguish between a single tap (navigate to details) and a double tap (add to favorites).
First, update your template:
<div *ngIf="posts"> <ion-card *ngFor="let post of posts" (click)="handlePostInteraction(post.postID)"> <div id="profileImage" > <img id="profileImageIn" [src]="post.profileImage"> </div> <div id="userName" ><h6>{{post.username}}</h6></div> <img [src]="post.image"> </ion-card> </div>
Then add the logic to your Tab4.ts file (don't forget to import Router):
import { ToastController, Router } from '@ionic/angular'; constructor( private aff: AngularFireFunctions, public toastController: ToastController, private router: Router // Add Router dependency ) {} private lastClickTimestamp = 0; async handlePostInteraction(postID: string) { const currentTime = Date.now(); const timeSinceLastClick = currentTime - this.lastClickTimestamp; // Detect double tap (adjust the 300ms threshold if needed) if (timeSinceLastClick < 300) { await this.doSomething(); // Trigger favorite action } else { // Single tap: navigate to post details this.router.navigate(['/tabs/details-feed/', postID]); } this.lastClickTimestamp = currentTime; } async doSomething() { const toast = await this.toastController.create({ message: 'Added to favorites.', duration: 2000 }); toast.present(); }
Notes
- For Solution 1, tweak the 300ms timeout interval if needed to match how quickly your users are likely to double-tap.
- Solution 2 gives you full control over interaction logic, making it easy to add more tap-based behaviors (like triple taps) later on.
内容的提问来源于stack exchange,提问作者user12075155

