如何使用指令停止事件传播?

How to stop event propagation using directive?

我有一个指令仅在其他 angular 应用程序中有效,但在 Ionic 中 angular 它不起作用。

该指令检查用户是否已登录,如果没有,则打开带有一些说明的弹出窗口。

当用户未登录时,我有弹出窗口并且可以正常工作,但是尽管有 preventDefault/stopPropagation 等等,事件还是被触发了。

这是代码:

View.component.html

<ion-icon name="pricetag-outline" onlyLogged authorized="true" (click)="saveNews(news)" ></ion-icon>

仅-logged.directive.ts

import { Directive, ElementRef, OnInit, HostListener, Input } from '@angular/core';
import { PopoverController } from '@ionic/angular';
import { AuthService } from '../services/auth.service';
import { OnlyLoggedComponent } from '../components/only-logged/only-logged.component';
@Directive({
    selector: '[onlyLogged]'
})
export class OnlyLoggedDirective implements OnInit {

    @Input() authorized = false;
    isUserLogged: boolean;

    constructor(private auth: AuthService, public popoverController: PopoverController) { }

    @HostListener('click', ['$event'])
    clickEvent(event) {

         if (!this.isUserLogged) {
            console.log(event);
            event.preventDefault();
            event.stopPropagation();
            event.stopImmediatePropagation();
            event.returnValue = false;

            event.buttonDisabled = true;

            this.openLogin(event);

            return false;
        }
    }



    ngOnInit() {
        this.auth.isAuthenticated.subscribe((authenticated) => {
            this.isUserLogged = authenticated;
        });
    }


    async openLogin(ev: any) {
        const popover = await this.popoverController.create({
            component: OnlyLoggedComponent,
            event: ev,
            translucent: true,
            animated: true,
            size: 'auto'
        });
        await popover.present();

        const { role } = await popover.onDidDismiss();
        console.log('onDidDismiss resolved with role', role);
    }

}

离子版本:6.18.1 Angular:13.0.3 节点:16.13.2

我进行了很多搜索,但没有找到解决方案...有人可以告诉我我做错了什么吗?

根据您的问题,我了解到您正在尝试使用 @HostListener 指令拦截点击事件。

我实际上也无法使用 hostlistener 使这个请求的行为起作用。

在我看来,问题是 stopPropagationbubbling 模式下会阻止事件从子级触发到父级。

但问题是您试图根据某些条件阻止点击元素本身。

换句话说你需要恰恰相反,你需要在capturing mode中应用stopPropagation,从父到子

我的建议是使用rxjs fromEvent - https://rxjs.dev/api/index/function/fromEvent

import { Directive, ElementRef, HostListener, Input } from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';

@Directive({
    selector: '[onlyLogged]'
})
export class OnlyLoggedDirective {
    sub = new Subscription();
    logged: boolean = true;

    constructor(private elRef: ElementRef) {}

    ngOnInit() {
        const el = this.elRef.nativeElement;
        this.sub = fromEvent(el.parentNode, 'click', { capture: true})
        .subscribe( (ev: any) => {
            if(ev.target == el) { this.checkLogin(ev); }
        })
    }

    checkLogin(ev: any) {
        if(!this.logged) {
            console.log("user is not logged in", );
            ev.stopImmediatePropagation();
            this.openLogin(ev);
        } else {
            console.log("user is logged in"); 
        }
    }

    openLogin(ev: any) {
        console.log('onDidDismiss resolved with role');
    }
}



<ion-content [fullscreen]="true">
  <div onlyLogged (click)="run()">click on me</div>
</ion-content>

 run() {
    console.log("This click has to be prevented, when user is not logged     in");
 }