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

Angular使用@ViewChild共享组件布尔属性时ngAfterViewInit报undefined错误

问题原因及修复方案

报错根因

enableLoginForm是app.component中ngAfterViewInit阶段的undefined属性
这个报错是多个问题共同导致的:

  • 子组件<redirect-user-to-mobile-app>受模板中*ngIf="!isLoading && isMobileDevice() && !isLogged"条件控制渲染,ngAfterViewInit执行时如果条件不满足,子组件还未渲染,@ViewChild获取到的redirectComponent就是undefined,访问它的属性自然报错。
  • AppComponent中没有声明enableLoginForm属性,模板直接使用该变量也会出现未定义报错。
  • 子组件的enableLoginForm是内部状态,变化时父组件无法自动感知,即使通过ViewChild拿到子组件实例,也不能响应后续的状态更新。
  • 原RedirectUserToMobileAppComponent代码中使用了this.router.navigate但构造函数没有注入Router,运行时也会报错。

修复步骤

1. 修改子组件RedirectUserToMobileAppComponent,新增输出事件抛出状态变化

import {
    Component,
    OnInit,
    Output,
    EventEmitter,
} from '@angular/core';
import { Router } from '@angular/router';

@Component({
    selector: 'redirect-user-to-mobile-app',
    templateUrl: './redirect-user-to-mobile-app.component.html',
    styleUrls: ['./redirect-user-to-mobile-app.component.sass'],
})
export class RedirectUserToMobileAppComponent implements OnInit {
    // 新增输出事件
    @Output() loginFormEnable = new EventEmitter<boolean>();
    enableLoginForm = false;

    // 注入Router
    constructor(private router: Router) {}

    ngOnInit(): void {}

    OnLogin(): void {
        this.enableLoginForm = true;
        // 状态变化时抛出事件
        this.loginFormEnable.emit(true);
        this.router.navigate(['../login']);
    }
}

2. 修改父组件AppComponent,声明对应属性接收状态

import {
    Component,
    HostListener,
    OnDestroy,
    OnInit,
    AfterViewInit,
} from '@angular/core';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import { FirebaseService } from './services/firebase/firebase.service';
import {
    SnakeMessage,
    SnakeMessageService,
} from './services/snakeMessage/snakeMessage.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { Subscription } from 'rxjs';
import { StorageService } from './services/storage/storage.service';
import { AuthService } from './services/auth/auth.service';

@Component({
    selector: 'app-component',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit, OnDestroy, AfterViewInit {
    favIcon: HTMLLinkElement = document.querySelector('#appIcon');
    private snakeMessageSub: Subscription;
    isLoading = true;
    isLogged: boolean;
    // 新增属性存储登录表单开关状态
    enableLoginForm = false;

    constructor(
        private matIconRegistry: MatIconRegistry,
        private firebaseService: FirebaseService,
        private snakeMessageService: SnakeMessageService,
        private _snackBar: MatSnackBar,
        private storageService: StorageService,
        private domSanitizer: DomSanitizer,
        private authService: AuthService
    ) {
        this.registerCustomIcons();
        this.storageService.initDB();
        this.storageService.onLoaded$.subscribe((loaded) => {
            if (loaded) {
                this.isLoading = false;
            }
        });
        this.isLogged = this.authService.isLoggedIn;
    }

    // 新增方法接收子组件抛出的状态
    onLoginFormEnable(status: boolean) {
        this.enableLoginForm = status;
    }

    ngAfterViewInit() {
        // 删掉原来访问redirectComponent的代码,不再需要
    }

    ngOnInit(): void {
        this.snakeMessageSub = this.snakeMessageService.messageSub.subscribe(
            (snakeMessage: SnakeMessage) => {
                this._snackBar.open(snakeMessage.message, snakeMessage.action, {
                    duration: 3000,
                    horizontalPosition: 'center',
                    verticalPosition: 'top',
                });
            }
        );
    }

    // 原代码缺失的registerCustomIcons、ngOnDestroy方法请自行保留
}

3. 修改app.component.html模板,绑定子组件输出事件

<ng-container *ngIf="!isLoading">
<ng-container *ngIf="isMobileDevice() && !isLogged">
    <!-- 绑定子组件的输出事件 -->
    <redirect-user-to-mobile-app (loginFormEnable)="onLoginFormEnable($event)"> </redirect-user-to-mobile-app>
    <router-outlet
        *ngIf="enableLoginForm"
    ></router-outlet>
</ng-container>

<router-outlet *ngIf="!isMobileDevice()"></router-outlet>
</ng-container>

内容的提问来源于stack exchange,提问作者Wahéb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 00:18:01