42

我查看了几个相关的帖子和​​文档,但似乎仍然无法从@ViewChild 获得预期的行为。

最终,我试图设置一个 div 的滚动位置。此元素不是组件,而是我的 HTML 中的普通 div。

为此,我尝试使用@ViewChild 来获取我需要的DOM 元素,并设置它的滚动值。(顺便说一句,如果您知道没有@ViewChild(或jQuery)的更好方法来完成此任务,我们将非常感谢您的回答!)

目前,@ViewChild 只返回 undefined。进行一些虚拟检查: - 我正在 AfterViewInit 中访问我的元素 - 我在此元素上没有任何其他指令,如 *ngIf 或 *ngFor。

这是控制器:

import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core';

@Component({
    selector: 'portfolio-page',
    templateUrl: './portfolio-page.component.html',
    styleUrls: ['./portfolio-page.component.scss']
})

export class PortfolioPageComponent implements AfterViewInit{
    @ViewChild('gallery-container') galleryContainer: ElementRef;

    ngAfterViewInit(){
        console.log('My element: ' + this.galleryContainer);
    }
}

和模板:

<div id='gallery-container' class='gallery-image-container'>
    <div class='gallery-padding'></div>
    <img class='gallery-image' src='{{ coverPhotoVm }}' />
    <img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>

我的输出很简单:我的元素:未定义。

如您所见,我目前正在尝试通过 ID 访问元素,但也尝试过类名。任何人都可以提供更多关于 ViewChild 选择器查询的详细信息吗?

我还看到了将哈希“#”用作@ViewChild 使用的选择器标识符的示例——但这会导致我使用#gallery-container 时出现模板解析错误。

我想不出这里还有什么可能是错误的。感谢所有帮助,谢谢!

此处提供完整代码:https ://github.com/aconfee/KimbyArting/tree/master/client/KimbyArting/components/portfolio-page

4

6 回答 6

69

尝试在模板中使用 ref:

<div id='gallery-container' #galleryContainer class='gallery-image-container'>
    <div class='gallery-padding'></div>
    <img class='gallery-image' src='{{ coverPhotoVm }}' />
    <img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>

并使用 ref 名称作为参数:

@ViewChild('galleryContainer') galleryContainer: ElementRef;

编辑

忘了提一下,这样声明的任何视图子视图只有在视图初始化后才可用。第一次发生这种情况是在ngAfterViewInit(导入并实现AfterViewInit接口)。

引用名称不能包含破折号,否则这将不起作用

于 2016-08-31T22:25:30.313 回答
28

有时,如果在您访问组件时组件尚未初始化,您会收到一条错误消息,指出子组件未定义。

但是,即使您在 AfterViewInit 中访问子组件,有时 @ViewChild 仍然返回 null。该问题可能是由 *ngIf 或其他指令引起的。

解决方案是使用@ViewChildren 而不是@ViewChild 并订阅组件准备就绪时执行的更改订阅。

例如,如果在父组件ParentComponent 中要访问子组件MyComponent。

import { Component, ViewChildren, AfterViewInit, QueryList } from '@angular/core';
import { MyComponent } from './mycomponent.component';

export class ParentComponent implements AfterViewInit
{
  //other code emitted for clarity

  @ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent>;

  public ngAfterViewInit(): void
  {
    this.childrenComponent.changes.subscribe((comps: QueryList<MyComponent>) =>
    {
      // Now you can access the child component
    });
  }
}
于 2018-01-12T16:09:50.213 回答
2

订阅更改

@ViewChildren(MyComponent) childrenComponent: QueryList<MyComponent>

确认工作,结合setTimeout()notifyOnChanges()仔细null检查。

任何其他方法都会产生不可靠的结果并且难以测试。

于 2018-01-15T15:10:39.920 回答
0

这是 ViewChild 使用 DOM 元素的 .ts 文件代码

import { Component, AfterViewInit, ViewChild, ElementRef } from '@angular/core';

@Component({

    selector: 'portfolio-page',
    templateUrl: './portfolio-page.component.html',
    styleUrls: ['./portfolio-page.component.scss']
})

export class PortfolioPageComponent implements AfterViewInit{

    @ViewChild('galleryContainer') galleryContainer: ElementRef;

    ngAfterViewInit(){
        console.log('My element: ' + this.galleryContainer);
    }
}

这是您的 .html 文件代码

    <div #galleryContainer class='gallery-image-container'>
    <div class='gallery-padding'></div>
    <img class='gallery-image' src='{{ coverPhotoVm }}' />
    <img class='gallery-image' src='{{ imagepath }}' *ngFor='let imagepath of imagesVm' />
</div>

希望能帮助到你!

于 2019-12-02T06:01:23.007 回答
0

我有一个类似的问题。与您不同,我@ViewChild返回了一个有效的ElementRef,但是当我尝试访问它时nativeElement,它是undefined.

我通过将视图设置为idlike #content,not like来解决它#content = "ngModel"

<textarea type = "text"
    id = "content"
    name = "content"
    #content
    [(ngModel)] = "article.content"
    required></textarea>
于 2019-01-17T11:45:26.130 回答
-1

另一种可能的情况是,当您在 angular 或 ionic 框架中使用 typescript 并从具有类似 javascript 签名的函数中调用 ViewChild 元素时。请改用类似函数签名的打字稿(例如使用粗箭头 =>)。例如

accessViewChild(){
    console.log(this.galleryContainer.nativeElement.innerHTML);
}

但是会显示 print undefined

accessViewChild = ()=>{
    console.log(this.galleryContainer.nativeElement.innerHTML);
}

将打印内部 html。

于 2019-12-02T01:17:29.973 回答