【问题标题】:Get ViewChild from base component in nesten component从嵌套组件中的基础组件获取 ViewChild
【发布时间】:2018-04-26 10:17:51
【问题描述】:

我有三个非常相似的自定义下拉组件:

  1. 基础下拉菜单
  2. 搜索下拉菜单
  3. 带有高级搜索功能的下拉菜单

他们有许多共同的行为,但也有一些不同。我决定将它们分成三个不同的组件,因为当它是一个具有 20 个 @Input() 属性和许多 if else 用于选择一种或其他行为的大组件时,这很糟糕。他们也有相同的下拉选项。所以唯一的区别是 input(header, idk 如何正确调用它) 和 button-press 处理程序。 这里是简化的example

所以我在base-dropdown 组件中有setDropdownPosition() 方法。它计算应该在哪里打开下拉菜单 - 在输入上方或下方。在dropdown-witch-search 组件中,我可以访问父方法,例如toggleOptions()setDropdownPosition()。但我无权访问父 @ViewChild('dropdownContainer') dropdownContainer: ElementRef; 以将他定位在扩展组件中。并且setDropdownPosition() 抛出一个错误。早些时候我在每个组件中都有自己的模板(并且它可以工作),但是每个模板中有很多可重复的东西,就像我之前提到的 - 选项等。 解决此问题的最佳方法是什么?谢谢

【问题讨论】:

  • 您的实际期望是什么?
  • 正如我在问题中所描述的,我想要不同的下拉组件。 Base-dropdown - 没什么特别的 - 它就像现在一样工作。但是对于dropdown-witch-search,我希望拥有基本下拉菜单的功能以及更多内容,我将把它们作为内容放入<base-dropdown>。现在在dropdown-witch-search 我没有@ViewChild('dropdownContainer') dropdownContainer 的访问权限,我无法选择在哪里显示组件
  • 将所有逻辑都放在一个组件中,并使用input 来区分它们。
  • 你读过这个问题吗?我写道:“我决定将它们分成三个不同的组件,因为当它是一个具有 20 个 @Input() 属性的大组件时,如果要选择一种或其他行为的话,那是很糟糕的”,您建议将所有组件合二为一。 ..

标签: javascript angular angular5


【解决方案1】:

我不确定你想要什么,所以我会解释这两种方法:

  1. 从父组件获取子变量

    @ViewChild(ChildComponent) child: ChildComponent; // One child
    @ViewChildren(ChildComponent) children: QueryList<ChildComponent>; // Several children
    
    ngOnInit() {
      this.child.someVariable = 'foo';
    }
    
  2. 从子节点获取父节点

注射器

constructor(private injector: Injector){
  let parentComponent = this.injector.get(ParentComponent);
}

通过输入

父母

parent = this;

孩子

@Input() parent: ParentComponent;
...
<app-child [parent]="parent"></app-child>

直接注入

constructor(@Inject(forwardRef(() => ParentComponent)) private parent:ParentComponent) {}

【讨论】:

  • 感谢您的快速回复。我已经在 stackoverflow 上看到了这个答案,但这不是我需要的。似乎不可能以优雅的方式做到这一点。我不能只获取 parentComponent 并在this 中使用它,因为嵌套组件dropdown-with-search 也有自己的变量和函数。所以问题是现在它可以使用所有base-dropdown 方法。但它不能使用父 ViewChild 引用...
  • this 是对父级的reference,所以是的,您可以获得父级。再说一次,我真的不明白你的目标。但是,如果它与父组件和子组件之间的通信有关,那么这个答案会为您提供所有可能的方式。
  • 我的目标是拥有一个具有所有常用功能的base-dropdown。所有继承的组件,如描述的dropdown-with-search 都会有一些额外的行为,如果有必要的话会覆盖base-dropdown 的一些功能等等,但大部分会使用base-dropdown 的方法。在继承的组件中,我只能使用来自base-component 的所有方法,例如this.toggleOptions()。但我不能对模板参考做同样的事情。我不能在从base-dropdown 继承的dropdown-with-child @ViewChild 引用中使用。
  • 当然,我可以从模板中覆盖使用@ViewChild refbase-component 方法。例如在base-dropdown 中:setFocus() { this.templateRef.nativeElement.focus() }dropdown-with-search 中我可以使用上面描述的内容覆盖它:constructor(@Inject(forwardRef(() =&gt; ParentComponent)) private parent:ParentComponent) { } setFocus() { this.parent.templateRef.nativeElement.focus() } 但它会产生太匹配的样板,因为我有很多长函数在base-dropdown 中使用this.templateRef
  • 如果你想要你的组件之间有共同的行为,那么就创建一个超类和/或一个接口。因为 Angular 组件不是为此而生的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
  • 2019-08-08
  • 1970-01-01
  • 2017-10-27
  • 2013-10-20
  • 2019-05-24
  • 2017-12-31
相关资源
最近更新 更多