You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 11中如何获取ContentChild的TemplateRef渲染后的宽高

错误原因

你的写法存在两个核心问题:

  1. TemplateRef是Angular模板的抽象引用,仅代表模板的结构定义,本身不对应任何实际渲染的DOM节点,给@ContentChild(TemplateRef)添加read: ElementRef配置会拿到无效引用,自然会触发报错。
  2. *ngFor渲染列表是异步操作,ngAfterViewInit生命周期触发时,列表的DOM节点大概率还没有完成渲染,此时查询DOM只能拿到undefined。

解决方案

修改思路是直接查询动态渲染后的卡片容器,等容器渲染完成后再从容器中读取子元素的尺寸,具体实现如下:

1. 修改组件模板

给每个包裹卡片的列容器添加模板引用变量#cardContainer:

<div class="row">
  <div class="col-lg-4 col-md-6" *ngFor="let i of items" #cardContainer>
    <ng-container *ngTemplateOutlet="template; context: {$implicit: i}"></ng-container>
  </div>
</div>

2. 修改组件逻辑

用@ViewChildren查询所有卡片容器,监听容器渲染完成后读取尺寸:

import { Component, Input, ContentChild, TemplateRef, ViewChildren, QueryList, ElementRef, AfterViewInit, AfterViewChecked } from '@angular/core';

@Component({
  selector: 'app-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.scss']
})
export class ListComponent implements AfterViewInit, AfterViewChecked {
  @Input() items: any[];
  @ContentChild(TemplateRef) template: TemplateRef<any>;
  // 查询所有卡片容器
  @ViewChildren('cardContainer') cardContainers: QueryList<ElementRef<HTMLDivElement>>;

  // 避免重复计算尺寸的标记
  private sizeCalculated = false;

  ngAfterViewInit(): void {
    // 监听容器变化,当列表项动态更新时重新计算尺寸
    this.cardContainers.changes.subscribe(() => {
      this.sizeCalculated = false;
    });
  }

  ngAfterViewChecked(): void {
    // 仅当容器渲染完成、未计算过尺寸、列表有值时执行逻辑
    if (this.cardContainers.length && !this.sizeCalculated && this.items?.length) {
      this.sizeCalculated = true;
      this.cardContainers.forEach((container, index) => {
        // 容器的第一个子元素就是你投影的卡片DOM节点
        const cardDom = container.nativeElement.firstElementChild;
        if (cardDom) {
          const cardWidth = cardDom.offsetWidth;
          const cardHeight = cardDom.offsetHeight;
          console.log(`第${index + 1}张卡片尺寸:宽${cardWidth}px,高${cardHeight}px`);
          // 此处添加你调整其他UI组件布局的逻辑
        }
      });
    }
  }
}

注意事项

  • 如果卡片内部存在异步加载的内容(比如图片、异步请求渲染的内容),需要等待内容加载完成后再读取尺寸,否则会拿到未渲染完成的错误值,这种场景可以给卡片内的异步资源添加load事件监听,或者用MutationObserver监听卡片内容变化。
  • offsetWidth/offsetHeight返回的是包含边框、内边距的实际渲染尺寸,如果你需要不含边框的尺寸可以改用clientWidth/clientHeight。

内容的提问来源于stack exchange,提问作者RRGT19

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 18:45:00