在 Angular 2 中使用影子 DOM 时 Node.contains() 是不是有效?

Posted

技术标签:

【中文标题】在 Angular 2 中使用影子 DOM 时 Node.contains() 是不是有效?【英文标题】:Does Node.contains() work when working with shadow DOM in Angular 2?在 Angular 2 中使用影子 DOM 时 Node.contains() 是否有效? 【发布时间】:2018-06-07 04:53:30 【问题描述】:

我在文档中的任何地方都找不到这个,但是当我单击作为父组件一部分的组件内的某些内容时,我的 Node.contains() 函数不起作用。

我的父组件如下所示:

<div class="body">
    <div class="item" *ngFor="let item of sortedItems;">
        <cv-checkbox></cv-checkbox>
        <cv-svg-icon></cv-svg-icon>
    </div>

    <div class="drop-zones" *ngFor="let zone of sortedItems.length + 1 | numberToArrayPipe;>
        <div class="drop-zone"></div>
    </div>
</div>

如您所见,我的父组件中有两个 Angular 组件:cv-checkboxcv-svg-icon。我向父组件添加了一个指令,如下所示:

<cv-layer-manager cvClickOutside (clickOutside)="toggleLayerManager()"></cv-layer-manager>

我在哪里检查单击的节点是否包含在父级中,如下所示:

@HostListener('document:click', ['$event']) public onClick(event: MouseEvent) 
    const clickedInside = this._elementRef.nativeElement.contains(event.target);
    if (!clickedInside) 
        this.clickOutside.emit();
    

如果我单击普通的 html 组件,一切都会按预期工作,但当我单击 Angular 组件时却不行。 contains 不检查 Angular 组件内部是否正确?

【问题讨论】:

【参考方案1】:

请检查您是否像 ngIf 或 ngSwitch 一样刷新,以便子组件消失。因此,当您执行 parentComponent.contains(childComponent) 时,尽管您实际单击时存在,但它不会工作。我昨天观察到这个此代码不起作用,我不得不部分使用它来解决问题。谢谢。

【讨论】:

这是正确而简单的答案。 - .contains() 不适用于具有 *ngIf*ngSwitch 的元素 - 最简单的解决方案是使用 [hidden]='myVar' 绑定,这将像 AngularJs 中的 ng-hide 一样工作,而不是从 DOM 中删除元素,而只是制作它不可见。更多关于[hidden]='myVar':***.com/a/35578093/1484847【参考方案2】:

我在使用日期选择器时遇到了类似的问题。为了解决这个问题,我向当前组件添加了 allowClose 属性。

@ViewChild('element') elementRef: ElementRef;
private allowClose = true;

然后我添加了另一个 HostListener,它只监听当前组件的事件。

@HostListener('click', ['$event'])
clickInside(event: any) 
  this.allowClose = false;

然后我修改了我的 clickOutside 方法以仅在 allowClose 为 true 时处理关闭,然后再次将 allowClose 设置回 true。

@HostListener('document:click', ['$event'])
clickOutside(event: any) 
  if (!this.elementRef.nativeElement.contains(event.target) && this.allowClose) 
    this.handleClose();
  
  this.allowClose = true;

就是这样!

【讨论】:

以上是关于在 Angular 2 中使用影子 DOM 时 Node.contains() 是不是有效?的主要内容,如果未能解决你的问题,请参考以下文章

HTML 中的影子 dom

聚合物、影子 dom、事件和冒泡

position: fixed 应该如何在影子 DOM 根中工作?

影子 DOM 中的 React 组件时单击事件未触发

为啥`Selection.isCollapsed` 在影子 DOM 中总是正确的?

如何在影子 DOM 中定位 ::part 属性的子项