从子组件获取父组件的elementRef

Rob*_*nik 6 typescript angular angular5

我有ParentComponentChildComponent。使用父组件,ng-content因此它可以在任何种类的DOM元素层次结构之内和之中具有任何内容。

我的子组件有一个具体要求:

  1. 孩子点击是切换其细节显示
  2. 如果将child放置在内部ParentComponent,则单击parent时,child应该做与1中相同的操作。

由于父级可以有任何内容,因此添加@ContentChild到父级似乎是不合理的,因为...封装良好。

因此,唯一应处理的地方是ChildComponent。到达ParentComponent很容易,方法是:

// ChildComponent ctor
constructor(@Optional() parent: ParentComponent) { ... }
Run Code Online (Sandbox Code Playgroud)

但这无济于事,因为我需要父组件,ElementRef以便能够将click事件处理程序附加到它。

如何获得Angular方式?

我知道我可以得到ChildComponent' ElementRef并向上遍历DOM来寻找最接近的ParentComponent'元素,但这可能比正确的Angular方法更像是一种hack。我很确定一定有更好的方法。

Jot*_*edo 1

我想到了 ATM 2 的想法:

1)将父组件作为可选参数注入到子组件中:

对于这种情况,父级应通过公共成员公开 elementRef 实例。

优点

  • 易于实施

对比

  • 子级与父级的紧密耦合:如果现在您有 N 种类型的父级怎么办?您会在子构造函数中定义 N-Optional 属性吗?为所有父母使用基类?在这种情况下,您将必须在所有 N 父组件上的组件级别使用显式提供程序。

2)在父子之间共享服务实例以跟踪点击事件

在这种情况下,父级和子级共享一个服务的公共实例,该实例或多或少如下所示:

export class ClickTracker {
   private readonly _clicks$ = new Subject<void>();
   readonly clicks$ = this._clicks$.asObservable();

   ngOnDestroy(){
      this._click$.complete();
   }

   click(){
      this._clicks$.next(); 
   }
}
Run Code Online (Sandbox Code Playgroud)

基本上,父级和子级都可以通过该方法发出新事件click。他们还可以使用公共流订阅该流clicks$并在事件上运行逻辑。

对于要在 DOM 层次结构中共享的实例,必须在父组件级别提供 ClickTracker 类的新实例:

@Component({
  providers: [ClickTracker]
})
export class FooParent{}
Run Code Online (Sandbox Code Playgroud)

分层依赖注入器将负责提供包含在父组件实例中的FooParent子组件。ClickTracker

优点:

  • 孩子和父母之间没有紧密耦合

对比:

  • 家长现在负责创建新服务。