angular2:可以停用守卫

angular2: CanDeactivate guard

我创建了一个 CanDeactivate 守卫,它 return 是一个可观察对象,它应用于一个组件,该组件加载到一个内部嵌套的路由器插座中。每当一个人试图导航到另一个 url 时,是否应该调用这个守卫?我问这个是因为我的情况没有发生。

在我的例子中,守卫只会在第一个 "different" URL 时被召唤。让我试着用一个例子来解释它。假设我总是 returning false 并且我试图从同一组件导航到不同的 urls:

/A --> guard called
/B --> guard called
/B --> no navigation and no guard called
/A --> guard called
/A -->guard not called and no navigation

这是预期的行为吗?

edit 嗯,好像是。刚刚构建了一个包含 3 个组件的小样本,并且只会在用户第一次尝试导航到特定 url 时调用守卫...这真的很奇怪...

无论如何,这是我使用的代码:

// app.routing
import {NgModule} from "@angular/core";
import {Routes, RouterModule, Route, CanDeactivate, ActivatedRouteSnapshot, 
        RouterStateSnapshot} from "@angular/router";
import { MainComponent } from "./main/main.component";
import { OtherComponent } from "./other/other.component";
import { Other3Component } from "./other3/other3.component";
import {Observable} from "rxjs/observable";
const fallback: Route = {
    path: "**",
    redirectTo: "/main",
    pathMatch: "full"
};
export class Test implements CanDeactivate<MainComponent>{
  canDeactivate(component: MainComponent, route: ActivatedRouteSnapshot, 
            state: RouterStateSnapshot): Observable<boolean> | boolean{
    console.log("in");
    return false;
  }
}
export const rotas: Routes = [
{
    path: "main",
    component: MainComponent,
    canDeactivate: [Test]
},
{
    path: "other",
    component: OtherComponent
},
{
    path: "other3",
    component: Other3Component
},
fallback
];

@NgModule({
 imports: [RouterModule.forRoot(rotas)],
 exports: [RouterModule]
})
export class AppRoutingModule{}

//app.component.html <h1> <a routerLink="/main">Main</a> <a routerLink="/other">Other</a> <a routerLink="/other3">Other3</a> </h1>

所有内容都是通过 angular-cli 生成的(例如:n g 组件 XXX)。是的,CanDeactivate 守卫将始终 return false 因此您将无法卸载主要组件。所以,我第一次点击其他时,警卫被召唤。如果再次单击其他,则不会呼叫守卫。但是,如果我点击 other3,就会呼叫守卫。在我点击其他 link(例如:其他)...

之前,点击其他 3 不会真正执行任何操作

这是预期的行为吗?我必须说,每次我击中另一个人时,我都希望我的后卫被击中 link...

谢谢。

路易斯

该死的,错误...自我注意:下次,先检查问题板

https://github.com/angular/angular/issues/12851#event-880719778

我找到了这个解决方案,而不是为每个组件创建一个 candeactivate 守卫,您将创建一个守卫服务并为每个要添加此选项的组件添加一个 candeactivate 方法,因此首先您必须添加此服务文件 "deactivate-guard.service.ts":

import { Injectable } from '@angular/core';
import { CanDeactivate } from '@angular/router';
import { Observable } from 'rxjs/Observable';

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

@Injectable()
export class DeactivateGuardService implements  CanDeactivate<CanComponentDeactivate>{

  canDeactivate(component: CanComponentDeactivate) {
    return component.canDeactivate ? component.canDeactivate() : true;
  }
}

那么你必须在应用模块中提供:

providers: [
    DeactivateGuardService
  ]

现在在要保护的组件中,添加函数:

export class ExampleComponent {
    loading: boolean = false;
    //some behaviour that change the loading value
    canDeactivate() {
        console.log('i am navigating away');
        if (this.loading) {
            console.log('no, you wont navigate anywhere');
            return false;
        }
        console.log('you are going away, goodby');
        return true;
    }
}

你可以看到变量加载是组件本地的。 最后一步是将指令添加到路由模块中的组件:

{ 
  path: 'example', 
  canDeactivate: [DeactivateGuardService],
  component: ExampleComponent 
}

就是这样,我希望这对您有所帮助,祝您好运。