我有一个简单的 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/