如何从孩子的父母访问模板引用变量?

Posted

技术标签:

【中文标题】如何从孩子的父母访问模板引用变量?【英文标题】:How to access template reference variables from parent in a child? 【发布时间】:2018-04-07 01:41:48 【问题描述】:

我正试图分别了解 Angular2 和 Typescript。我想要做的是从子组件中的按钮打开一个sidenav - 这里是app-header

我知道我可以打开它

<button mat-button (click)="sidenav.open()">Open sidenav</button>

但这只有在我将它放在父模板中时才有效,因为它引用了模板变量引用sidenav。但是,正如我所说,我想通过点击一个孩子的按钮来打开它。

这将是我的布局/应用程序模板:

<mat-sidenav-container>
  <mat-sidenav #sidenav>
    <!-- sidenav content -->
    Here comes the menu ..
  </mat-sidenav>

  <div>    
    <app-header>
      <!-- Application header -->
    </app-header>
  </div>

</mat-sidenav-container>

这将是标题模板:

<div>
  header for title works!
  <button mat-button (click)="sidenav.open()">Open sidenav</button>
</div>

当然这会失败,因为我无法引用 sidenav - 那么我如何才能正确地从孩子内部访问 sidenav

或者在 Angular2 中传递这样的引用是“不”,我实际上应该使用基于事件的触发器或类似的东西?

【问题讨论】:

sidenav 变量到底指的是什么?你能告诉我们那个代码吗? 【参考方案1】:

这是正常的父/子组件通信。您可以这样做的方法是只在孩子上公开一个输出事件:

parent.component.html 摘录:

<child-component (openNav)="sidenav.open()"></child-component>

在孩子中,您只需将按钮单击绑定到发出该事件:

child.component.ts:

@Output() openNav = new EventEmitter();

child.component.html:

<button (click)="openNav.emit()">Open Nav</button>

但是,由于这是一个可能需要在很多地方甚至嵌套的地方访问的 sidenav,您可能只想解决所有情况的问题并使用可观察的共享服务:

side-nav.service.ts:

@Injectable()
export class SideNavService 
    private openNavSource = new Subject(); // never expose subjects directly
    openNav$ = this.openNavSource.asObservable();

    openNav = () => this.openNavSource.next();

适当提供,注入到父子中使用

parent.component.ts:

@ViewChild('sidenav') sidenav; // get your template reference in the component
constructor(private sideNavService: SideNavService)  
private sideNavSub;
ngOnInit() 
   this.sideNavSub = this.sideNavService.openNav$.subscribe(() => this.sidenav.open());

ngOnDestroy() 
   this.sideNavSub.unsubscribe(); //clean your subscriptions

child.component.ts:

constructor(private sideNavService: SideNavService)  
openNav() 
   this.sideNavService.openNav(); // looks repetitive but accessing injectd services in templates is bad practice and will cause pains down the line

child.component.html:

<button (click)="openNav()">Open Nav</button>

然后您可以将服务注入任意组件并根据需要使用它。

【讨论】:

非常棒!感谢您提供这两种方法,因为我肯定迟早会同时使用它们! :) 我可以问一个小问题:像(openNav) 这样的“参数”是什么?这是子视图的某种构造函数参数吗?为什么在第一个示例中是@Output 而不是@Input (openNav) 是标准的角度输出事件绑定。子组件正在输出一个事件,而父组件通过该语法绑定到它。这是一个@Output,因为它是从子级生成的输出,而不是从父级传递给子级的输入。一个例子是您熟悉的 (click)="" 语法。 click 是一个 Angular 框架,提供来自原生 HTML 组件的输出事件,以便于绑定。 啊,明白了。再次感谢! :) 绝对精彩 非常感谢@bryan60 ...第二种方法绝对是一种。干杯

以上是关于如何从孩子的父母访问模板引用变量?的主要内容,如果未能解决你的问题,请参考以下文章

Python:在分叉的孩子和父母之间共享变量

从组件类访问模板引用变量

React,如何从父母那里访问孩子的状态?无需更新父母的状态

如何从子类访问父类数据成员,当父母和孩子的日成员具有相同的名称时

Angular2 - 父母和孩子通过服务进行交流

无法在角度 6 中访问从父母到孩子的方法