Cordova+Angular:如何在main.ts中使用Router实现页面跳转
Great question! Let's walk through why you're hitting injection issues and the best ways to handle this scenario.
Why Router Injection Fails in main.ts
The main.ts file is your Angular app's entry point, but at the time you're trying to inject RouterModule, Angular's dependency injection (DI) container hasn't fully initialized. Unlike HttpClientModule (which has fewer dependencies tied to the app's routing state), Router relies on several services like ActivatedRoute, Location, and routing configuration that only become available after the app has finished bootstrapping. That's why your earlier approach with HttpClient worked but Router doesn't.
Solution 1: Access Router After App Bootstraps in main.ts
If you really need to handle the resume event directly in main.ts, you can wait for the app to finish bootstrapping and then retrieve the Router instance from the module's injector. Here's how:
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { Router } from '@angular/router'; platformBrowserDynamic().bootstrapModule(AppModule) .then(moduleRef => { // Get Router from the initialized injector const router = moduleRef.injector.get(Router); // Listen for Cordova's resume event document.addEventListener('resume', () => { // Your conditional check here const shouldNavigateHome = true; // Replace with your actual condition if (shouldNavigateHome) { router.navigate(['/home']); } }); }) .catch(err => console.error(err));
This works because after bootstrapModule resolves, the DI container is fully set up, and all Router dependencies are ready to use.
Solution 2: (Recommended) Listen for Events in an Angular Component/Service
A cleaner, more Angular-idiomatic approach is to handle the resume event inside a root component (like AppComponent) or a dedicated service. This way, you can use normal dependency injection without worrying about initialization timing.
Example in AppComponent:
import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { constructor(private router: Router) {} ngOnInit(): void { // Ensure Cordova is ready before attaching event listeners document.addEventListener('deviceready', () => { document.addEventListener('resume', () => { // Your conditional logic const shouldNavigateHome = true; // Replace with your condition if (shouldNavigateHome) { this.router.navigate(['/home']); } }); }); } }
Example with a Dedicated Service:
Create a DeviceEventService to encapsulate Cordova event handling:
import { Injectable } from '@angular/core'; import { Router } from '@angular/router'; @Injectable({ providedIn: 'root' }) export class DeviceEventService { constructor(private router: Router) {} init(): void { document.addEventListener('deviceready', () => { document.addEventListener('resume', () => { this.handleResume(); }); }); } private handleResume(): void { const shouldNavigateHome = true; // Your condition if (shouldNavigateHome) { this.router.navigate(['/home']); } } }
Then initialize it in AppComponent:
import { Component, OnInit } from '@angular/core'; import { DeviceEventService } from './services/device-event.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { constructor(private deviceEventService: DeviceEventService) {} ngOnInit(): void { this.deviceEventService.init(); } }
Which Approach Should You Choose?
- Use the
main.tsmethod only if you need to start listening for theresumeevent as early as possible (though in most cases, the root component approach is sufficient). - The component/service approach is preferred because it aligns with Angular's lifecycle, makes your code more maintainable, and leverages Angular's DI system naturally.
内容的提问来源于stack exchange,提问作者Yermiyahu Tesler

