Angular13中ViewChild获取SwiperComponent实例为undefined问题
问题原因
swiperSlideShow实例返回undefined,核心是模板配置缺失,附带2个易忽略的代码错误:
- 模板内的
<swiper>组件未添加#swiperSlideShow模板引用变量,@ViewChild('swiperSlideShow')无法匹配到目标组件,是返回undefined的直接原因 - 播放/暂停按钮的
click事件未添加方法调用括号,点击时不会实际执行对应逻辑 ngAfterViewInit生命周期内直接调用autoplay.start()路径错误,Swiper原生实例挂载在组件的swiperRef属性下,无法直接从SwiperComponent实例访问
修复方案
1. 修正模板代码
给swiper标签添加对应模板引用,同时修复按钮事件绑定:
<h1 class="azure">Graph Statistics</h1> <button (click)="startCarousell()" class="azure">Play</button> <button (click)="stopCarousell()" class="azure">Pause</button> <div> <!-- 新增#swiperSlideShow模板引用,和@ViewChild声明的查询名对应 --> <swiper #swiperSlideShow [config]="config"> <div class="swiper-wrapper"> <iframe class="swiper-slide" *ngFor="let point of endPoints" [src]="point.src | safe"> </iframe> </div> <div class="swiper-pagination"></div> <div class="swiper-button-next"></div> <div class="swiper-button-prev"></div> </swiper> </div>
2. 修正组件逻辑
调整Swiper方法调用路径,兼容异步数据加载场景,避免变更检查报错:
import { Component, OnInit, ViewChild} from '@angular/core'; import { SwiperOptions} from 'swiper'; import { SwiperComponent } from 'swiper/angular'; import { EndPointService } from './end-point.service'; import { GraphSite } from './GraphSite'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { @ViewChild('swiperSlideShow') swiperSlideShow!: SwiperComponent; endPoints: GraphSite[] =[]; config: SwiperOptions = { // 初始化时关闭自动播放,等实例获取完成后手动启动,避免实例未就绪时自动播放报错 autoplay: false, pagination: { el: '.swiper-pagination', clickable: true }, navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev' }, spaceBetween: 30 }; constructor(private endPointService: EndPointService){} ngOnInit(){ this.getEndPoints(); } ngAfterViewInit(): void { // 通过swiperRef访问原生Swiper实例,setTimeout规避变更检查报错 setTimeout(() => { this.swiperSlideShow.swiperRef.autoplay.start(); }, 0); } getEndPoints(){ this.endPointService.getEndPoints().subscribe(endPoints => { this.endPoints = endPoints; // 异步数据加载完成后更新Swiper实例,重新计算slide布局 setTimeout(() => { this.swiperSlideShow?.swiperRef.update(); this.swiperSlideShow?.swiperRef.autoplay.start(); }, 0); }); } startCarousell(){ this.swiperSlideShow.swiperRef.autoplay.start(); } stopCarousell(){ this.swiperSlideShow.swiperRef.autoplay.stop(); } }
注意事项
@ViewChild查询依赖模板引用变量标记,未添加#名称标记时,即使组件存在也无法被查询到,该问题出现概率远高于*ngIf导致的视图未渲染问题swiper/angular封装的组件不会直接暴露原生Swiper的API,所有原生方法、属性都需要通过swiperRef属性访问- 轮播slide为异步加载时,数据赋值完成后必须调用
swiperRef.update()触发Swiper重新计算布局,否则会出现轮播空白、无法切换、自动播放终止等问题
内容的提问来源于stack exchange,提问作者softwareplay
相关产品推荐
相关产品推荐

