elementRef的宽度发生变化时如何更改模板

Posted

技术标签:

【中文标题】elementRef的宽度发生变化时如何更改模板【英文标题】:How to change template when width of elementRef changed 【发布时间】:2021-06-04 02:31:59 【问题描述】:

我尝试在 ngInit 中加载一些数据并将 div 的宽度设置为等于接收到的数据。然后我尝试使用 ViewChild 和 ElementRef 在 ngAfterViewInit 中设置一些样式选项,但我的 elementRef 始终未定义。我该如何解决?

我的组件:

export class NewComponent implements OnInit, AfterViewInit 
    public data: number = 0;
    public showMe: bool = false;
    public redColor: bool = false;
    @ViewChild('myElement',  static: false) myElement;

    constructor(private myService: MyService) 

    public ngOnInit(): void 
        this.myService.loadData().subscribe(result => this.data = result);
    

    public ngAfterViewInit(): void 
        console.log(this.myElement); // undefined
        console.log(this.myElement.nativeElement); // Cannot read property 'nativeElement' of undefined
        this.setStyleOptions(); 
    

    public setStyleOptions() 
        if (this.myElement.nativeElement.clientWidth > 50) 
            this.showMe = true;
            this.redColor = true;
        
        else 
            this.showMe = false;
            this.redColor = false;
        
    

我的模板:

<div *ngIf="some-condition">
    <div *ngIf="some-new-condition">
        <div #myElement [style.width.px]=data"></div>
        <div *ngIf="showMe" [class.red]="redColor">Text</div>
    </div>
</div>

我知道 elementRef 可能由于 *ngIf 指令而未定义,但我不能用 [hidden] 替换它,因为我必须替换所有外部 div 块中的指令。我也尝试使用 ViewChild setter,比如这里@ViewChild in *ngIf:

private myElement: ElementRef;
@ViewChild('myElement',  static: false) set content(content: ElementRef) 
    if (content) 
        this.myElement = content;
        this.setStyleOptions();
    

但随后“Еxpression has changed after it was checked”出现在控制台中。 设置超时也无济于事。

如何正确更改模板?

【问题讨论】:

运行detectChanges(),有时它有助于验证更改。 【参考方案1】:

当您在某个条件下有“ViewChild”时,您需要“更改 Angular”来重新绘制。所以,一般来说你需要

condition=true;  //first makes the condition true
setTimeout(()=>  //say Angular to "repaint" and then execute the function
  this.setStyleOptions()
)

您也可以使用changeDetectorRef。也就是说,你在构造函数中注入它

constructor (private cdr:ChangeDetectorRef)

并使用

condition=true;  //first makes the condition true
this.cdr.markForCheck()     //say Angular to "repaint" 
this.setStyleOptions()  //then execute the function

【讨论】:

我不应该接触外部条件(我的示例中的一些条件,一些新条件)。还有其他方法可以获取包含 ngIf 指令的 elementRef 吗? 我想说,如果您的 ViewChild 在 *ngIf 下,您需要先使为真,重新绘制然后使用 ViewChild,您不能为真并调用 ViewChild,因为 Angular 没有时间重绘

以上是关于elementRef的宽度发生变化时如何更改模板的主要内容,如果未能解决你的问题,请参考以下文章

更改宽度或高度时如何保留 UIImageView 的宽度:高度比

如何监听div内容的改变?

jQuery位置,仅在窗口宽度发生变化时重新加载

tableViewCell 的高度和宽度在快速滚动时发生变化

属性指令:在初始化时获取 ElementRef 宽度

如何防止 sizeToFit 更改 UILabel 宽度?