angular - 如何在 Angular2 的特定路径上操作组件

标签 angular angular2-routing

我有一个简单的 TopbarComponent它基本上在我的 View 顶部添加了一个引导导航栏。

因为我 90% 的模板都应该包含这个指令,所以我想通过我的 app.component 来处理它看起来像这样:

import ...;

@Component({
    selector: 'my-app',
    templateUrl: 'app/app.component.html',
    directives: [ROUTER_DIRECTIVES, TopbarComponent, ...],
    providers: [ROUTER_PROVIDERS, ...]
})

@RouteConfig([
{
    path: '/login',
    name: 'Login',
    component: LoginComponent
},
{
    path: '/dashboard',
    name: 'Dashboard',
    component: DashboardComponent,
    useAsDefault: true
}
])

它的模板看起来像这样:

<my-topbar></my-topbar>

<div class="container-fluid">
    <div class="row">
        <router-outlet></router-outlet>
    </div>
</div>

现在我想使用ngIf (或除了用 css 隐藏它之外的任何其他方式)隐藏几条路线上的顶部栏,如 /login例如。 我尝试了几种使用 @CanAcitvate() 的方法或实现 OnActivate在我的 LoginComponent (以及从我的 AppComponent 尝试它)但没有效果(甚至有问题甚至无法触发功能)。 我得到的最接近的是使用 Router直接在我的AppComponent像这样:

export class AppComponent implements OnInit{
    showTopbar:boolean;

    constructor(private _router:Router) {}

    ngOnInit():any {
        this.showTopbar = this._router.lastNavigationAttempt != '/login';
    }
}

在我的 app.component.html我将指令更改为 <my-topbar *ngIf="showTopbar"></my-topbar>

但这只适用于我的应用程序的初始加载,因为 ngOnInit不会在每次状态更改时触发。是否有类似的方法我可以使用(只是找不到)或者我是不是走错了方向?


编辑:

目前,PierreDuc 的答案对我不起作用,但我使用 location.path() 尝试了类似的方法。像这样:

constructor(private _location:Location) {}

private get _hideTopbar() : boolean {
    switch(this._location.path()){
        case '/register':
        case '/login':
            return true;
        default:
            return false;
    }
};

太糟糕了,我不能使用 data @RouteConfig中的属性(property)在这种方法中。感觉会更好。

最佳答案

一段时间以来,我一直在为类似的问题绞尽脑汁。 我找到的解决方案一开始可能会被视为棘手,但将来可以为我解决许多此类类似问题。

基本上,您必须让 router-outlet 在路由更改时发出一个事件,让您的 AppComponent 监听该自定义事件。

第一步是创建自定义路由器 socket :

@Directive({
selector: 'custom-router-outlet'
})
export class CustomRouterOutlet extends RouterOutlet {
    private parentRouter:Router;

    constructor(_elementRef: ElementRef,
            _loader: DynamicComponentLoader,
            _parentRouter: Router,
            @Attribute('name') nameAttr: string) {
    super(_elementRef, _loader, _parentRouter, nameAttr);
    this.parentRouter = _parentRouter;
    }

    activate(nextInstruction: ComponentInstruction): Promise<any> {
        //***YOUR CUSTOM LOGIC HERE***
        return super.activate(nextInstruction);
    }
}

这是自定义路由器 socket 的非常基本的实现。您的逻辑必须在 activate 方法中实现,在每次路由更改时调用。 在此方法中,您可以检查 route 的数据属性。

主要问题是,目前指令不能发出事件...它们只接受输入,不能触发任何输出...

我找到了解决这个问题的方法:使用 EventEmitter 创建一个 Service 用于组件和指令之间的通信:

@Injectable()
export class PubsubService {
    private _pubSubber: EventEmitter<any> = new EventEmitter();

    routeisChanging(obj:any) {
        this._pubSubber.emit(obj);
    }

    onRouteChanged() {
        return this._pubSubber;
    }
}

AppComponent 订阅了 onRouteChanged 事件:

subscription:any;
constructor(private _pubsubService:PubsubService) {
    this.subscription = this._pubsubService.onRouteChanged().subscribe(data => {
        /**YOUR CUSTOM LOGIC HERE*/});
}

CustomRouterOutlet 在需要时触发 activate 方法中的事件:

activate(nextInstruction: ComponentInstruction): Promise<any> {
    //***YOUR CUSTOM LOGIC HERE***
    this._pubsubService.routeisChanging(nextInstruction.routeData.data['hideTopbar']);
    return super.activate(nextInstruction);
}

通过这种方式,您可以使用任何逻辑轻松实现路由器和 AppComponent 之间的通信。

您必须记住在应用的 RootComponent 中注入(inject)通信服务。

关于angular - 如何在 Angular2 的特定路径上操作组件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36814390/

相关文章:

angular - 使用 mutate() 时,为什么 Angular 信号不运行我的自定义 'equal' 检查?

angular - 路由器导航无法正常工作

angular - 将 Angular 7 升级到 8,错误 : this. typeChecker.getTypeArguments 不是构建库上的函数

Angular2 传递数据以从组件路由

angular - 为什么每次都会重复调用 ngOnInit

html - url中没有哈希的Angular2

angular - Protractor :未检测到 Angular 应用程序

angular - 从我的浏览器/服务器获取时区以注入(inject) angular2-highcharts

javascript - Angular2 强制/硬重新加载浏览器缓存脚本?

angular - 如何在延迟加载 angular 2 NgModule 中为 loadchildren 提供正确的路径名?