【问题标题】:angular2: CanDeactivate guardangular2: CanDeactivate 防护
【发布时间】:2016-12-14 16:52:48
【问题描述】:

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

在我的例子中,守卫只会被第一个“不同”的 URL 调用。让我试着用一个例子来解释它。假设我总是返回 false 并且我试图从同一个组件导航到不同的 url:

/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 component XXX)。是的,CanDeactivate 守卫将始终返回 false,因此您将无法卸载主要组件。所以,当我第一次点击其他时,守卫被召唤了。如果再次单击其他,则不会调用任何守卫。但是,如果我点击 other3,那么守卫就会被召唤。在我点击其他链接(例如:其他)之前,点击 other3 不会真正做任何事情......

这是预期的行为吗?我必须说,我希望每次我点击另一个链接时我的后卫都会受到打击......

谢谢。

路易斯

【问题讨论】:

    标签: angular angular2-routing angular2-guards


    【解决方案1】:

    我找到了这个解决方案,而不是为每个组件创建一个 candeactivate 保护,您将创建一个保护服务并为每个要添加此选项的组件添加一个 candeactivate 方法,因此首先您必须添加此服务文件“停用-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;
        }
    }
    

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

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

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

    【讨论】:

    • 谢谢,非常好的解决方案。
    • 我有几乎完全相同的代码,但是在调用警卫时,它抱怨组件未定义。在我的组件中,我正在导入接口,类实现它,并且该方法返回一个布尔值。 DeactivateGuardServicecanDeactivate方法是如何获取组件的?
    【解决方案2】:

    该死的,bug...提醒自己:下次,先检查问题板

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-10
      • 1970-01-01
      • 2013-11-12
      相关资源
      最近更新 更多