Ionic 5调用Service中IonSlides方法报slideNext未定义错误求助
问题根因
@ViewChild是Angular仅适用于组件、指令的视图查询装饰器,只能查询当前组件模板内的元素/子组件。你在全局Service中使用@ViewChild('slides')是完全无效的,Service没有关联的视图模板,所以内部的slides属性永远是undefined,调用slideNext时就会抛出你遇到的类型错误。- 每个页面自行通过
@ViewChild获取的当前页面IonSlides实例没有传递给Service,Service无法拿到对应页面的轮播实例,自然无法执行操作。
修复步骤
1. 修改全局Service代码
删除Service中无效的@ViewChild声明、slideOptions配置,调整所有操作轮播的方法,将IonSlides实例作为入参传入:
import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; import { IonSlides } from '@ionic/angular'; @Injectable({ providedIn: 'root' }) export class HttpService { constructor(private router: Router){} async navigate(){ this.router.navigate(['tabs/tab2']) await this.waitBefore(10); this.router.navigate(['/quiz-maison']) } isOK:boolean=null; answers: any; hasAnswered: boolean = false; initState: boolean = false; score: number = 0; // 新增slides入参,使用传入的实例操作 showAnswer(event:any, slides: IonSlides) { this.answers = event.target.value; if (this.answers=="correct"){ this.isOK=true; this.score++; } else { this.isOK=false; } this.hasAnswered = true; console.log("I'm showAnswer fct"); console.log(slides); slides.slideNext(); } ionSlideChange(){ this.answers =null; this.isOK=null; this.hasAnswered = false; } waitBefore(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } // 新增slides入参 async goNextSlide(slides: IonSlides){ await this.waitBefore(1000); slides.slideNext(); slides.lockSwipeToPrev(true); console.log("I'm goNextSlide fct"); } }
2. 修改页面调用逻辑
页面调用Service方法时,将自身通过@ViewChild获取到的slides实例传入:
import { Component, OnInit, ViewChild } from '@angular/core'; import { IonSlides } from '@ionic/angular'; import { HttpService } from '../../service/http.service'; @Component({ selector: 'app-quiz-maison', templateUrl: './quiz-maison.page.html', styleUrls: ['./quiz-maison.page.scss'], }) export class QuizMaisonPage implements OnInit { @ViewChild('slides') slides: IonSlides; slideOptions = { initialSlide: 0, slidesPerView: 1, autoplay: false, pagination : { el: '.swiper-pagination', clickable: true }, slideShadows: true, }; constructor(private http:HttpService){} ngOnInit() { } showAnswer(event: any){ // 传入当前页面的slides实例 this.http.showAnswer(event, this.slides) } goNextSlide(){ // 传入当前页面的slides实例 this.http.goNextSlide(this.slides); } goToAnswers(){ // 该方法如果也操作slides,同理新增参数传入实例即可 // this.http.goToAnswers(this.slides); } ionSlideChange(){ this.http.ionSlideChange() } }
注意事项
@ViewChild查询到的元素需要在ngAfterViewInit生命周期之后才会完成初始化,不要在ngOnInit阶段调用操作slides的方法,避免拿到undefined。- 不同页面的slides实例是独立的,通过入参传递的方式可以保证Service操作的是当前页面的轮播组件,不会出现页面间实例冲突的问题。
内容的提问来源于stack exchange,提问作者FreeMok
相关产品推荐
相关产品推荐

