【问题标题】:Child components and DI context子组件和 DI 上下文
【发布时间】:2017-12-05 00:52:43
【问题描述】:

我有一个具有各种搜索类型的应用程序 - 但是这些搜索之间的许多功能是相同的,此外,除了一些字符串(面板标题等)之外,视图几乎相同。

我有一个基本 SearchComponent 和一个 Specialized 搜索组件。 Specialized 搜索组件在标记中实例化基本 SearchComponent 并设置适当的输入。

每个专门的搜索组件使用不同的搜索策略,即服务实例和方法以及结果的映射。

目前我在实例化基础组件时将函数引用绑定到父函数,以便可以调用父函数。但是看起来 DI 上下文是不同的,所以它抱怨我在父级中注入的服务没有找到。

我该如何解决这个问题?

例子:

在 search-base.ts 中:

  @Input() execSearchFn: (query) => Observable<any>;
  @Input() mapTableDataFn: (i: any) => any;

executeSearch(e) {  // Triggered by some event
  this.execSearchFn(e.query);  // delegate to parent for specialized search
}

在 xyz-search.html:

   <app-search-base #appSearchBase
    searchTitle="XYZ Search"
    [execSearchFn]="execSearch"
    [mapTableDataFn]="mapTableData">
  </app-search-base>

在 xyz-search.ts 中:

constructor(private xyzService: XYZService) {}

execSearch(query: string) {
 return this.xyzService.search(query);  // does not work! xyzService is undefined!
}

这很好用,调用了父级中的函数,但找不到任何注入的属性。

错误是“无法读取未定义的属性搜索”。果然 xyzService 被注入并在构造函数中定义,但由于调用上下文来自基本组件,它在 execSearch 函数中未定义。

我的目标功能类似于在基类中定义一个抽象方法和一个为该抽象方法定义确切行为的子类。但是 Angular 不允许使用抽象组件,因此必须使用上述解决方法。事实上,我可以创建一个常规的抽象基类,但是我不能重用标记。我需要重用基本功能和基本标记。

我猜最好的方法是发出一个执行事件(而不是使用函数引用),然后通过 Input() 将结果发回??这听起来太令人费解了。

【问题讨论】:

    标签: angular


    【解决方案1】:

    嗯,这很难理解。只是为了澄清我做对了:您试图让子组件(这里是搜索库)执行一个操作,并希望在父组件(这里是您的 xyz 搜索)中对其做出反应。

    这通常是函数上output 绑定的一个很好的例子。您当前正在提供一个函数作为输入变量,为您的子组件提供代码,而不是发出调用作为它的输出。这是一种肮脏的方式,它有局限性。你找到了,因为仅仅给出代码就会失去上下文。

    所以这就是我要做的。我会将您的功能从输入更改为输出,只需几个简单的步骤即可完成。这是父组件。

    <app-search-base #appSearchBase
        searchTitle="XYZ Search"
        (onExecSearch)="execSearch($event)"
        [mapTableDataFn]="mapTableData">
     </app-search-base>
    

    我们只需要使用括号并在此处使用 $event 参数调用父母 execSearch 函数(这是至关重要的,所以不要忘记这一点)。括号将绑定类型从input 更改为output。我将子函数重命名为onExecSearch,以便更清楚地表明当发生某些事情时会调用它。

    现在在子组件中,我们必须通过输出事件发射器使用给定的输出函数。如果您想这样称呼它,这是一种常见的角度模式。

    @Output() onExecSearch: new EventEmitter<string>();
    
    executeSearch(e) {   
      this.onExecSearch.emit(e.query); 
    }
    

    我们可以通过在onExecSearch 发射器上发射一个正确类型的值来调用父级提供的输出函数。您的父 execSearch 函数绑定到发射器,因此当 onExecSearch 调用其 emit 函数时会调用它,但这样它会在正确的上下文中执行此操作。

    子组件公开一个 EventEmitter 属性 当事情发生时发出事件。父级绑定到该事件 属性并对这些事件做出反应。

    你的 XYZ-search.ts 甚至没有改变,它应该被正确调用。

    更多信息,请查看this教程,他们可能会比我解释得更好。

    【讨论】:

    • 谢谢!我在想这是我唯一的选择,我试图使用一种更简单的方法,因为我必须使用 ngOnChanges 监控 Input()
    • 将输出(执行)和输入(结果)分开的缺点之一是我丢失了 ngOnChanges 中原始事件的上下文。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    相关资源
    最近更新 更多