有没有一种简洁的方法来获取当前路由组件的引用?
这个方法似乎可以工作,但看起来很hacky:
this.router.currentInstruction.
component.componentType.prototype.somePropertyOrFunction();
有没有一种简洁的方法来获取当前路由组件的引用?
这个方法似乎可以工作,但看起来很hacky:
this.router.currentInstruction.
component.componentType.prototype.somePropertyOrFunction();
@Component({
selector: 'some-cmp',
template: `
<div>routerOnActivate: {{log}}</div>
`})
export class SomeCmp implements OnActivate {
constructor(private service:RouteStateService) {
}
routerOnActivate(next: ComponentInstruction, prev: ComponentInstruction) {
this.service.setCurrentRouteComponent(this);
}
}
var component = this.service.getCurrentRouteComponent();
可以使用RouterOutletMap
访问组件实例,它是Angular使用的一种有状态服务,用于存储由router-outlet
指令渲染的实例。您可能需要以下类型:
import { Router, RouterOutletMap, RouterOutlet } from '@angular/router';
顶级outletMap
是router
的属性,但在TS中不可见,因此您可能需要将其转换为any
:
constructor(private router:Router) {
const rootOutletMap:RouterOutletMap = (<any>this.router).outletMap;
}
RouterOutletMap
是一个 JavaScript 对象,它有一个属性 _outlets
。这个 _outlets
是一个哈希映射对象,通过出口名称包含 RouterOutlet
实例。如果一个出口没有名称,它将是“primary”。在获取了 RouterOutlet
之后,您可以获取组件实例:
const rootOutletMap:RouterOutletMap = (<any>this.router).outletMap,
outletsHash = (<any>rootOutletMap)._outlets,
primaryOutlet:RouteOutlet = outletsHash['primary'], // 'primary' is the default name
component = primaryOutlet.component; // <-- this is the instance
RouterOutletMap
是一棵树,因此根映射具有对子项的引用,以此类推。如果需要,您可以组织查找过程以找到特定路由的组件。以下是递归组件提取的示例:
// returns an array of all the router-outlets component currently rendered
private getComponentsChain(routerOutletMap: RouterOutletMap) {
const outlets: any = (<any>routerOutletMap)._outlets,
outletsList = [],
components = [];
_.forOwn(outlets, (value: RouterOutlet, key: string) => {
outletsList.push(value);
components.push(value.component);
});
const recursiveComponents = _.flatMap(
outletsList,
(o: RouterOutlet) => this.getComponentsChain(o.outletMap));
return [...components, ...recursiveComponents];
}
/* ...then somewhere in component: */
console.log(this.getComponentsChain((<any>this.router).outletMap));
如果您选择这种方式,请注意以下几点:
我发现的唯一简短但不太优美的方法是这样的(适用于Angular 4、6、7、8):
const currentComponent = (router as any).rootContexts.contexts
&& (router as any).rootContexts.contexts.get('primary')
&& (router as any).rootContexts.contexts.get('primary').outlet.component;
注意:这是一个 HACK,如果您有多个路由器出口等,则可能无法正常工作。
你可以从CanActivate守卫中获取组件的类型。例如:
@Injectable()
export class MyGuard: CanActivate
{
canActivate(route: ActivatedRouteSnapshot) : boolean{
let componentType = route.routeConfig.component;
}
}
prototype
,但它实际上并不是正确的实例。我添加了一个描述这一点的答案... - Thierry Templier