4

我正在尝试使用 canDeactivate 路由器防护。我传入的组件 (ClaimsViewComponent) 在代码第一次运行时为空。但在随后的运行中,代码按预期运行。我们试图弄清楚为什么组件在第一次运行时为空。

这是 canDeactivate 保护代码:

@Injectable()
export class ConfirmDeactivateGuard implements 
CanDeactivate<ClaimsViewComponent> {
  canDeactivate(target: ClaimsViewComponent): boolean {

      if (target.canDeactivate()) {
          return window.confirm('Do you really want to cancel?');
      }

      return true;
  }
}

这是路由模块代码:

const routes: Routes = [
{ path: ':type', component: ClaimsViewComponent, canDeactivate: 
[ConfirmDeactivateGuard] }
];

@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})

这是完整的错误堆栈:

TypeError: Cannot read property 'canDeactivate' of null
    at ConfirmDeactivateGuard.canDeactivate (confirm-deactivate-guard.ts:16)
    at MergeMapSubscriber.eval [as project] (router.js:3933)
    at MergeMapSubscriber._tryNext (mergeMap.js:128)
    at MergeMapSubscriber._next (mergeMap.js:118)
    at MergeMapSubscriber.Subscriber.next (Subscriber.js:95)
    at ArrayObservable._subscribe (ArrayObservable.js:116)
    at ArrayObservable.Observable._trySubscribe (Observable.js:172)
    at ArrayObservable.Observable.subscribe (Observable.js:160)
    at MergeMapOperator.call (mergeMap.js:92)
    at Observable.subscribe (Observable.js:157)
    at ConfirmDeactivateGuard.canDeactivate (confirm-deactivate-guard.ts:16)
    at MergeMapSubscriber.eval [as project] (router.js:3933)
    at MergeMapSubscriber._tryNext (mergeMap.js:128)
    at MergeMapSubscriber._next (mergeMap.js:118)
    at MergeMapSubscriber.Subscriber.next (Subscriber.js:95)
    at ArrayObservable._subscribe (ArrayObservable.js:116)
    at ArrayObservable.Observable._trySubscribe (Observable.js:172)
    at ArrayObservable.Observable.subscribe (Observable.js:160)
    at MergeMapOperator.call (mergeMap.js:92)
    at Observable.subscribe (Observable.js:157)
    at resolvePromise (zone.js:814)
    at resolvePromise (zone.js:771)
    at eval (zone.js:873)
    at ZoneDelegate.invokeTask (zone.js:421)
    at Object.onInvokeTask (core.js:4740)
    at ZoneDelegate.invokeTask (zone.js:420)
    at Zone.runTask (zone.js:188)
    at drainMicroTaskQueue (zone.js:595)

谢谢你。

4

2 回答 2

11

我通过在 page.module.ts 而不是 app.module.ts 中添加 canDeactivate 解决了这个问题

于 2019-05-22T09:40:18.920 回答
4

似乎,canDeactivate没有处理“延迟加载”。请检查您的路线,并确保您已设置该component属性。

更新@rohan-sampat 反馈。

有用。我的项目中也有 CanDeactivate 的问题。

CanDeactivate-guard.service.ts

import { Observable } from 'rxjs';
import { CanDeactivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

export interface CanComponentDeactivate {
  canComDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;  
}

export class CanDeactivateGuard implements CanDeactivate<CanComponentDeactivate> {

  canDeactivate(component: CanComponentDeactivate,
    currentRoute: ActivatedRouteSnapshot,
    currentState: RouterStateSnapshot,
    nextState?: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
    return component.canComDeactivate();
  }

}

这是我使用 CanDeactivate 进行验证的组件。

import { Component, EventEmitter, Output, OnInit } from "@angular/core";
import { DataService } from '../Shared/Service/DataService';
import { ActivatedRoute } from '@angular/router';
import { Subscription, Observable } from 'rxjs';
import { CanComponentDeactivate } from '../can-deactivate-guard.service';

@Component({
  selector: 'app-server',
  templateUrl: './server.component.html'
})

export class ServerComponent implements OnInit, CanComponentDeactivate {

  @Output() serverCreated = new EventEmitter<string>();

  queryParams: Subscription;
  data: string;

  canMove: false;

  userModel: any;
  constructor(private dataService: DataService, private route: ActivatedRoute) {

  }

  ngOnInit() {
    this.dataService.dataUpdate.subscribe(data => {
      this.data = data;
    })

    this.queryParams = this.route.queryParams.subscribe(data => {
      this.userModel = JSON.parse(data["model"]);
    })
  }


  canComDeactivate(): Observable<boolean> | Promise<boolean> | boolean {
    if (this.data == undefined || this.data == "") {
      var res = confirm("Text is blank");
      return res;
    }
    return this.canMove;
  }
}

我在其中定义了路由的 app.module.ts 文件。

const appRoutes: Routes = [
 // { path: '', loadChildren: () => import('./Login/login.module').then(l => l.LoginModule) },
  { path: 'login', loadChildren: () => import('./Login/login.module').then(l => l.LoginModule) },
  { path: 'server', canActivate: [AuthGuard], canDeactivate: [CanDeactivateGuard], loadChildren: () => import('./severs/server.module').then(s => s.ServerModule) },
  { path: '**', component: ErrorComponent },
];

路径服务器上的 CanDeactivate 导致问题。如果我试图转到模块外的另一条路径,那么 id 甚至不会击中 CanDeactivate 守卫。

但是,如果我将 CanDeactivate 从 app.module 放置到 server.routes 文件中,意味着在延迟加载的模块本身中对其进行验证,那么它可以正常工作,正如预期的那样。

服务器.route.ts 文件

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ServerComponent } from './server.component';
import { ErrorComponent } from './404.component';
import { CanDeactivateGuard } from '../can-deactivate-guard.service';

const route: Routes = [
  { path: '', component: ServerComponent },
  { path: 'server:/model', component: ServerComponent, canDeactivate: [CanDeactivateGuard] },
  { path: 'server', component: ServerComponent, canDeactivate: [CanDeactivateGuard] },

  { path: 'not-found', component: ServerComponent },
  //{ path: '**', component: ErrorComponent },

]

@NgModule({
  imports: [RouterModule.forChild(route)],
  exports: [RouterModule]
})

export class ServerRoute { }

现在,在解决方案发生这种变化之后,我的代码可以正常工作。希望这可以帮助。

于 2019-05-02T09:33:30.453 回答