navigateByUrl 无法路由应用程序

navigateByUrl is failing to route the application

我在标签页上有一个按钮,用于通过删除存储条目为用户重置应用程序:

export class Tab1Page {

  constructor(private router: Router, private storage: Storage, private toastController: ToastController) { }

  async resetSettings() {
    await this.storage.remove('welcomeComplete');

    const toast = await this.toastController.create({
      message: 'Your settings have been reset.',
      duration: 2000
    });
    await toast.present();

    console.log('before');
    this.router.navigateByUrl('/');
    console.log('after');
  }
}

在浏览器调试器中,我可以看到条目正在从存储中删除。我也得到了祝酒词。

但是,由于某种原因,navigateByUrl 方法似乎没有触发。 以上页面位于 url '/tabs/tab1'。两个 console.log() 语句都已执行,并且控制台中没有错误。

我是前端开发的新手,如果这是一个基本的新手问题,我深表歉意。


更新

我的应用-routing.module.ts

import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
import { WelcomeGuard } from './welcome/welcome.guard';

const routes: Routes = [
  { 
    path: '', 
    loadChildren: './tabs/tabs.module#TabsPageModule',
    canActivate: [WelcomeGuard]
  },
  { 
    path: 'welcome', 
    loadChildren: './welcome/welcome.module#WelcomePageModule',
  }
];
@NgModule({
  imports: [
    RouterModule.forRoot(routes, { enableTracing: true, preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}

我的welcome.guard.ts

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router, CanActivate } from '@angular/router';
import { Observable } from 'rxjs';
import { Storage } from '@ionic/storage';

@Injectable({
  providedIn: 'root'
})
export class WelcomeGuard implements CanActivate  {

  constructor(private router: Router, private storage: Storage) {}

  async canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Promise<boolean> {

    const welcomeComplete = await this.storage.get('welcomeComplete');

    if (!welcomeComplete) {
      this.router.navigateByUrl('/welcome');
    }
    return true;
  }
}

我已将我的 resetSettings() 更改为以下内容:

  async resetSettings() {
    await this.storage.remove('welcomeComplete');

    const toast = await this.toastController.create({
      message: 'Your settings have been reset.',
      duration: 2000
    });

    toast.onDidDismiss().then(() => {
      this.router.navigateByUrl('');
    });

    await toast.present();
  }

更改 resetSettings() 未能解决问题。

您是否应该尝试使用 navigate 而不是 navigateByUrl

this.router.navigate(['/']);

或者

this.router.navigate(['']);

你也可以

toast.onDidDismiss().then(()=> {
  this.router.navigate(['/']);
});

取决于您的路由器。

与其他人一样,我会检查您尝试导航的路线以匹配您的路由器路径配置:

this.router.navigateByUrl('/');

const routes: Routes = [
    {
        path: '/', component: YourComponent, pathMatch: 'full', data: {
        ...
        }
    },

我的默认路由通常是“ ”,而不是“ / ”。

他们在这里很好地介绍了如何使用 router.navigate / router.navigateByUrl:

如果您包含其余的相关代码,我们或许能够为您解决特定问题提供更多帮助。

希望对你有帮助

确保您的服务方法 return 是可观察的。

storage.service.ts

import { Observable } from 'rxjs';

remove() {

  const obs = Observable.create(observer => {
    observer.next('Hello');

    // Throw an error.
    if (error) {
      observer.error("my error");
    }

  });

  return obs;

}

toastController.service.ts

import { Observable } from 'rxjs';

create() {

  const obs = Observable.create(observer => {
    observer.next('Hello');

    // Throw an error.
    if (error) {
      observer.error("my error");
    }

  });

  return obs;

}

然后消费

import { zip } from 'rxjs';


export class Tab1Page {

  constructor(
    private router: Router, 
    private storage: Storage, 
    private toastController: ToastController
  ) { 
    // this.resetSettings();
  }

  resetSettings() {
    const a = this.storage.remove('welcomeComplete');
    const b = this.toastController.create({
      message: 'Your settings have been reset.',
      duration: 2000
    });

    zip(a, b).subscribe( res => {
       this.router.navigateByUrl('/');
       // or
       this.router.navigate(['/']);
    });

  }
}

router.navigatByUrl returns 带有布尔值的promise,表示路由是否成功。我会建议记录,你的路由是否成功是这样的:

this.router.navigateByUrl('/').then(success => console.log(`routing status: ${success}`));

我猜结果会是假的,因为你的警惕。因此,如果我是对的,请将 WelcomeGuard 从您的路线中删除或返回 true 以禁用它。

我猜问题的发生是因为再次在守卫内部路由,但两行后返回 true。

你的守卫有问题,下面welcome.guard.ts的变化可以帮助

 if (!welcomeComplete) {
   this.router.navigateByUrl('/welcome');
   return false;
 }
 return true;

原因:

调用后在 resetSetting 函数中

toast.onDidDismiss().then(() => {
  this.router.navigateByUrl('');
});

它尝试导航到 url : '' 匹配路由数组中的第一个对象

...
{ 
path: '', 
loadChildren: './tabs/tabs.module#TabsPageModule',
canActivate: [WelcomeGuard]
}
....

然后它执行保护功能,然后你返回 true 在任何情况下,这意味着页面已获准导航到“/”,正如你在 /tabs/tab1 这是当前路由设置的子路径,所以它什么也不做,停留在同一页面。

在我的例子中,这是因为在路径解析之前有一个重定向。

访问 / 时,我将用户重定向到 /login,以便可以加载登录页面。

然而,我使用的 path-matching 策略是 'prefix',这意味着 Angular 路由器将为任何前缀为 / 的路由选择重定向指令,即, 所有路线.

将 path-matching 策略更改为 'full' 指示 Angular 路由仅在完整路径为 / 时重定向到 /login。 因此,/ 被重定向到 /login/forgot-password 不再 被重定向到 /login

  { 
    path: '', 
    redirectTo: 'login', 
    pathMatch: 'prefix' // <---- this should be 'full'
  }, 
  {
    path: 'login',
    loadChildren: () => import('./login').then(m => m.LoginPageModule),
  },
  {
    path: 'forgot-password',
    loadChildren: () => import('./forgot-password').then(m => m.ForgotPasswordPageModule)
  },