Angular 4如何获取*ngIf隐藏组件的高度?附StackBlitz示例
解答你的Angular组件高度获取问题
首先明确说:通过OnInit钩子无法获取被*ngIf隐藏的组件高度。因为当*ngIf条件为false时,Angular根本不会渲染这个组件,对应的组件实例都没被创建,OnInit钩子自然不会触发,也就无从获取高度了。
那点击按钮显示组件后,怎么获取高度呢?这里有几种可靠的方法:
方法一:利用ViewChild + setTimeout(简单直接)
Angular修改DOM需要一定时间,点击按钮切换*ngIf条件后,DOM不会立即完成更新,用setTimeout可以让浏览器先完成渲染,再去获取高度:
父组件(控制显示的组件)代码示例:
import { Component, ViewChild } from '@angular/core'; import { ChildCompo } from './child.component'; @Component({ selector: 'app-parent', template: ` <button (click)="showChild = true">显示子组件</button> <child-comp *ngIf="showChild" #childRef></child-comp> ` }) export class ParentComponent { showChild = false; @ViewChild('childRef') childComponent!: ChildCompo; // 也可以直接在按钮点击事件里处理 onShowChild() { this.showChild = true; setTimeout(() => { const height = this.childComponent.getHeight(); console.log('子组件高度:', height); }, 0); } }
子组件代码修改:
给子组件添加一个获取高度的方法,通过ElementRef拿到自身DOM元素:
import { Component, ElementRef } from '@angular/core'; @Component({ selector: 'child-comp', templateUrl: './child.component.html' }) export class ChildCompo { constructor(private el: ElementRef) {} getHeight(): number { // offsetHeight包含padding、border,clientHeight只包含padding,按需选择 return this.el.nativeElement.offsetHeight; // 或者用 return this.el.nativeElement.clientHeight; } }
方法二:使用ChangeDetectorRef + AfterViewChecked(更贴合Angular机制)
如果不想用setTimeout,可以借助Angular的变更检测机制,在DOM更新完成后再获取高度:
import { Component, ViewChild, ChangeDetectorRef, AfterViewChecked } from '@angular/core'; import { ChildCompo } from './child.component'; @Component({ selector: 'app-parent', template: ` <button (click)="showChild = true">显示子组件</button> <child-comp *ngIf="showChild" #childRef></child-comp> ` }) export class ParentComponent implements AfterViewChecked { showChild = false; @ViewChild('childRef') childComponent!: ChildCompo; private hasFetchedHeight = false; // 避免重复执行 constructor(private cdr: ChangeDetectorRef) {} ngAfterViewChecked() { if (this.showChild && !this.hasFetchedHeight) { // 手动触发变更检测,确保DOM已完成更新 this.cdr.detectChanges(); const height = this.childComponent.getHeight(); console.log('子组件高度:', height); this.hasFetchedHeight = true; } } }
方法三:子组件内部监听自身渲染完成
如果想让子组件自己获取高度并处理,可以用AfterViewInit钩子——只有当*ngIf条件为true、组件完成渲染后,这个钩子才会触发:
import { Component, ElementRef, AfterViewInit, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'child-comp', templateUrl: './child.component.html' }) export class ChildCompo implements AfterViewInit { @Output() heightReady = new EventEmitter<number>(); constructor(private el: ElementRef) {} ngAfterViewInit() { const height = this.el.nativeElement.offsetHeight; console.log('子组件自身高度:', height); // 也可以把高度通过事件传给父组件 this.heightReady.emit(height); } }
父组件接收高度:
<button (click)="showChild = true">显示子组件</button> <child-comp *ngIf="showChild" (heightReady)="onChildHeightReady($event)"></child-comp>
onChildHeightReady(height: number) { console.log('从子组件拿到的高度:', height); }
总结一下:
*ngIf隐藏时组件未被渲染,OnInit钩子完全无法获取任何相关信息;- 组件显示后,必须等DOM更新完成再获取高度,推荐用
ViewChild配合setTimeout,或者用Angular原生的变更检测+生命周期钩子,也可以让子组件自己监听渲染完成事件。
内容的提问来源于stack exchange,提问作者ttmt
相关产品推荐
相关产品推荐

