使用指令检测角度 4 中的 Click 外部元素

Posted

技术标签:

【中文标题】使用指令检测角度 4 中的 Click 外部元素【英文标题】:Detect Click outside element in angular 4 using directives 【发布时间】:2018-02-11 03:30:30 【问题描述】:

我使用自定义指令来检测 Angular 2 中元素外部的点击,但在 Angular 4 中则不可能。

[plunkr]https://plnkr.co/edit/aKcZVQ?p=info

当我尝试在 angular-4 中使用相同的代码时,出现以下错误:

1. Argument of type ' template: string; directives: typeof ClickOutside[]; ' is not assignable to parameter of type 'Component'. ==> 

    @Component(
    templateUrl: "",
    directives: [ClickOutside]
    )


2. Type 'Subscription' is not assignable to type 'Observable<MouseEvent>'. in the directive inside ngOnInit() and ngOnDestroy() 

ngOnInit() 
    this.globalClick = Observable
        .fromEvent(document, 'click')
        .delay(1)
        .do(() => 
            this.listening = true;
         ).subscribe((event:MouseEvent) => 
            this.onGlobalClick(event);
         );


ngOnDestroy() 
    this.globalClick.unsubscribe();

如果 Angular 4 中的指令声明有任何变化,请告诉我,官方文档对此事没有帮助。

【问题讨论】:

糟糕,这个:***.com/a/45997092/5468463 @Vega 我正在使用相同的方法,但唯一的问题是应用程序需要 2000 毫秒的时间来处理每次点击,这很糟糕,因为这会扭曲用户体验 ng-click-outside 节点包似乎也适用于此目的。即使使用最新的 Angular 版本(目前 Angular 6+)似乎也可以使用。 (将此评论视为仅供参考) 【参考方案1】:

与您的 plnkr 相关的变化很少。

    NgModules,或者更确切地说看一下框架的Archietcture。该模块是您应该注册组件、服务和指令的地方 在模块中注册指令后,您不必在组件中导入它

指令本身对我来说看起来不错。我将您的指令与我在 Angular 4.3.5 中运行良好的指令进行了比较。

实际上,在这种情况下您不需要任何指令,除非它不会重复使用。如果您只需要将该 clickOutside 应用于菜单,最好这样做:

像这样将点击事件绑定到您的“内部”选择器。假设这是您的菜单:

  <ul id="menu" (click)="clickedInside($event)"> <li> .. </li> </ul>

然后在你的组件中添加clickedInside() 函数,如下所示:

  clickedInside($event: Event)
    $event.preventDefault();
    $event.stopPropagation();  // <- that will stop propagation on lower layers
    console.log("CLICKED INSIDE, MENU WON'T HIDE");
  

最后,您可以在组件中使用 Host Listener 将点击也绑定到文档的其余部分

  @HostListener('document:click', ['$event']) clickedOutside($event)
    // here you can hide your menu
    console.log("CLICKED OUTSIDE");
  

【讨论】:

这里有最小的工作演示:plnkr 请忽略上面的评论即使我停止降低元素菜单关闭时间是`2300ms这似乎是一个错误,但它确实有效 如果你隐藏的区域是一个dropzone怎么办?当我单击它时,“选择文件窗口”打开,但 clickedInside() 无法调用。如何缩小范围? 对我自己的回答:那么您将需要非常具体地测试该事件,幸运的是,组件的元素和类名非常独特:将此作为取消选择的 if 条件之一:!$event.path[0].classList[0].startsWith('dz')

以上是关于使用指令检测角度 4 中的 Click 外部元素的主要内容,如果未能解决你的问题,请参考以下文章

角度单击事件处理程序未触发更改检测

Vue.js 自定义指令使用 TypeScript 检测点击外部元素

我可以自动检测角度指令中的值而不是使用模板引用变量吗?

将 onclick/ng-click 事件附加到网格数据绑定事件中的元素

Vue 模板:如何自动将自定义属性添加到具有 v-on:click 指令的元素

取消绑定 ng-click 以获取角度中的动态 dom 元素