@Viewchild不在Directive中工作,但在Component中工作

问题描述 投票:4回答:2

我正在玩@ViewChild / @ ContentChild,我很惊讶地看到@ViewChild不在内部指令中运行并且对于component.But在指令中工作正常它不起作用。我尝试使用AfterViewInit钩子,所以生命周期钩子不是原因。其他问题在这里,请找到下面的代码。

app.component.html

<div appMain >
  <div #testContentDiv style="background-color: grey">
    <p>This is the first p tag</p>
    <p>This is the second p tag</p> 
  </div>
  <div #testViewDiv style="background-color: yellow">
    <p>This is the first p tag</p>
    <p>This is the second p tag</p>
  </div>
  <app-test-child></app-test-child>
</div>

test-dir.ts - 指令

import { Directive, ViewChild, ElementRef, OnInit, AfterViewInit, AfterContentInit, ContentChild } from '@angular/core';

@Directive({
  selector: '[appMain]'
})
export class MainDirective implements OnInit, AfterContentInit, AfterViewInit {

  constructor() { }
  // tslint:disable-next-line:member-ordering
  @ContentChild('testContentDiv') testContent: ElementRef;
  @ViewChild('testViewDiv') testView: ElementRef;
  ngOnInit() {
    //Called after the constructor, initializing input properties, and the first call to ngOnChanges.
    //Add 'implements OnInit' to the class.
    // console.log(this.test.nativeElement);

  }

  ngAfterContentInit() {
    //Called after ngOnInit when the component's or directive's content has been initialized.
    //Add 'implements AfterContentInit' to the class.
    console.log('Content Div: ngAfterContentInit:  ' + this.testContent.nativeElement);
    // console.log('View Div: ngAfterContentInit: ' + this.testView.nativeElement);


  }

  ngAfterViewInit() {
    //Called after ngAfterContentInit when the component's view has been initialized. Applies to components only.
    //Add 'implements AfterViewInit' to the class.
    console.log('Content Div:ngAfterViewInit: ' + this.testContent.nativeElement);
    console.log('View Div: ngAfterViewInit: ' + this.testView.nativeElement);

  }
}

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = "App works";

  constructor() {
  }
}
angular angular2-directives
2个回答
3
投票

Angular中有三种指令:

组件 - 带模板的指令。

结构指令 - 通过添加和删除DOM元素来更改DOM布局。

属性指令 - 更改元素,组件或其他指令的外观或行为。

因此,根据定义,组件是唯一带有template的指令,因此您只能为组件找到@ViewChild

阅读更多关于它here

希望这可以帮助!!


2
投票

至少从Angular v6.x开始:

根据Angular source code for directives,确实可以选择孩子。但是,仅使用@ViewChildren@ContentChildren装饰器的标准方法似乎对我不起作用。此外,尽管有文档,我仍然无法让@ViewChildren工作。

然而,@ContentChildren确实对我有用。你需要使用queries属性来装饰Directive本身(为了清楚起见,这个指令是愚蠢的,你仍然需要一个选择器和其他东西来使它工作):

@Directive({
  queries: {
    // Give this the same name as your local class property on the directive. "myChildren" in this case
    myChildren: new ContentChildren(YourChild),
  },
})
export class MyDirective implements AfterContentInit {
  // Define the query list as a property here, uninitialized.
  private myChildren: QueryList<YourChild>;

  /**
   * ngAfterContentInit Interface Method
   */
  public ngAfterContentInit() {
    // myChildren is now initialized and ready for use.
  }
}

这对我来说已经足够了,所以我不会浪费更多的时间来弄清楚为什么ViewChildren不起作用。我理解ViewChildrenContentChildrenis之间的区别,ContentChildren<ng-content>标签中选择,ViewChildren直接从视图本身中选择。所以,这种行为对我来说似乎是倒退的,但可能有其正当理由。

正如预期的那样,ContentChildrenngAfterContentInit挂钩之前是不可用的,所以不要让那个人咬你。

© www.soinside.com 2019 - 2024. All rights reserved.