Angular2 在 <router-outlet>s 中使用 @Inputs
Angular2 using @Inputs with <router-outlet>s
我的页面中有一个子导航,它在公共主视图下方显示一些子视图。我想通过 <router-outlet>
将一个对象传递给子视图,这样我就可以在主组件中检索一次数据,然后与我的子组件共享。
注意:如果我在 main.html 中包含指令 <one></one>
它会起作用,但这不是我想要的行为。
主视图:
<h1>Details</h1>
<a [router-link]="['./sub1']">One</a> |
<a [router-link]="['./sub2']">Two</a> |
<a [router-link]="['./sub3']">Three</a>
<hr/>
<router-outlet [data]="maindata"></router-outlet>
子视图 1:
<h2>{{ data.name }}</h2>
...
主视图:
@Component({
selector: 'main-detail',
directives: [ROUTER_DIRECTIVES],
templateUrl: './main.html'
})
@RouteConfig([
{ path: '/', redirectTo: '/one' },
{ path: '/one', as: 'One', component: OneComponent },
{ path: '/two', as: 'Two', component: TwoComponent },
{ path: '/three', as: 'Three', component: ThreeComponent }
])
export class MainComponent {
maindata: Object = {name:'jim'};
}
子视图 1:
@Component({
selector: 'one',
directives: [CORE_DIRECTIVES],
inputs: ['data'],
templateUrl: './one.html'
})
export class OneComponent {
@Input() data;
}
如果是简单的数据你可以通过RouteParams
<a [router-link]="['./sub3'],{name:'jim'}">Three</a>
然后在您的子视图中
@Component({
selector: 'one',
directives: [CORE_DIRECTIVES],
templateUrl: './one.html'
})
export class OneComponent {
data: any;
constructor(params: RouteParams){
this.data = params.get('data');
}
}
您还可以通过移动组件内部的 RouterConfig 来设置路由以始终从组件传递参数(注意,这不是通常的做法):
export class AppCmp {
history: string[] = [];
constructor(public list: PersonalizationList,
private router_: Router) {
list.get('histoy', (response) => {
this.history = response;
});
router_.config([
{ path: '/', component: HomeCmp, as: 'Home', data: this.history },
{ path: '/about', component: AboutCmp, as: 'About' }
]);
}
}
如果您打算做一些更复杂的事情,我建议使用服务在 routes/components 之间进行通信。这实际上是我喜欢的方式。
示例服务:
import {Injectable} from 'angular2/angular2';
@Injectable()
export class CarsService {
list1: array<any> = ['a','b','c','d'];
list2: array<any>;
constructor() {
this.list2 = [1,2,3,9,11];
}
}
如何注入服务:
export class Cars {
constructor(cars:CarsService) {
this.cmpList1 = cars.list1;
this.cmpList2 = cars.list2;
}
}
这样您就可以使用该服务进行通信,而无需考虑 parent/child 或其他奇怪的限制。
看起来语法已更改。下面对我有用~Angular4.0.0
HTML(传递路由参数)
<li><a [routerLink]="['/templatecreate',{mode:'New'}]">New Job</a></li>
组件
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.getTemplate();
this.sub = this.route.params.subscribe(params => { this.id = params['mode'];
console.log("Routing Mode", this.id);
});
}
我认为 Angular2 传递数据的正确方式是通过依赖注入(通过使用服务),否则用户将能够在浏览器 URL 中看到您传递的数据。
此外,使用服务将允许 "Separation of Concerns",这意味着组件 A 不应依赖于组件 B。
依赖注入链接:
1) https://angular.io/guide/dependency-injection
我们有一个很大的 angular 项目(刚从 Angular 开始,所以解决方案与我们的理解一样好:-))。
shell 组件可以调用 4 个(基于路由的)"action" 模块中的任何一个 - 其中每个模块都有自己的服务(但没有组件视图)并且可以调用 6 个中的任何一个(基于路由的)共享组件。共享组件在所有 4 个服务之间共享,因此它们不能有任何特定于调用模块的逻辑。
我们正在使用服务解析器 ActionModuleServiceResolver,它是所有 4 个操作服务的 DI。基于状态 (RouterStateSnapshot) URL,我们 return 相应的服务。
@Injectable()
export class ActionModuleServiceResolver implements Resolve<ActionModuleService> {
constructor(private _mod1: ModOneService,
private _mod2: ModTwoService, private _mod3: ModThreeService,private _mod4: ModFourService) { }
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): ActionModuleService {
if(state.url.includes(`/${ActionModuleType.ModOne}/`))
return this._mod1;
else if(state.url.includes(`/${ActionModuleType.ModTwo}/`))
return this._mod2;
....
else
return null;
}
}
每个动作模块的路由模块像这样路由到共享组件:
const routes: Routes = [
{
path: 'sharedMod1', component: SharedModOneComponent, data: {
title: `ModOne_SharedModOne`,
routeName: 'sharedMod1'
}, resolve: { actionModule: ActionModuleServiceResolver }
},
接下来各SharedModule通过DI获取激活路由,获取调用服务:
//SharedModOne.component.ts
constructor(protected route: ActivatedRoute) {}
ngOnInit() {
this.actionModSvc= this.route.snapshot.data['actionModule'];
this.actionModSvc.getDesignFile(this.route);
}
希望这对某人有所帮助,如果可以改进,请告诉我。
谢谢,
RDV
我的页面中有一个子导航,它在公共主视图下方显示一些子视图。我想通过 <router-outlet>
将一个对象传递给子视图,这样我就可以在主组件中检索一次数据,然后与我的子组件共享。
注意:如果我在 main.html 中包含指令 <one></one>
它会起作用,但这不是我想要的行为。
主视图:
<h1>Details</h1>
<a [router-link]="['./sub1']">One</a> |
<a [router-link]="['./sub2']">Two</a> |
<a [router-link]="['./sub3']">Three</a>
<hr/>
<router-outlet [data]="maindata"></router-outlet>
子视图 1:
<h2>{{ data.name }}</h2>
...
主视图:
@Component({
selector: 'main-detail',
directives: [ROUTER_DIRECTIVES],
templateUrl: './main.html'
})
@RouteConfig([
{ path: '/', redirectTo: '/one' },
{ path: '/one', as: 'One', component: OneComponent },
{ path: '/two', as: 'Two', component: TwoComponent },
{ path: '/three', as: 'Three', component: ThreeComponent }
])
export class MainComponent {
maindata: Object = {name:'jim'};
}
子视图 1:
@Component({
selector: 'one',
directives: [CORE_DIRECTIVES],
inputs: ['data'],
templateUrl: './one.html'
})
export class OneComponent {
@Input() data;
}
如果是简单的数据你可以通过RouteParams
<a [router-link]="['./sub3'],{name:'jim'}">Three</a>
然后在您的子视图中
@Component({
selector: 'one',
directives: [CORE_DIRECTIVES],
templateUrl: './one.html'
})
export class OneComponent {
data: any;
constructor(params: RouteParams){
this.data = params.get('data');
}
}
您还可以通过移动组件内部的 RouterConfig 来设置路由以始终从组件传递参数(注意,这不是通常的做法):
export class AppCmp {
history: string[] = [];
constructor(public list: PersonalizationList,
private router_: Router) {
list.get('histoy', (response) => {
this.history = response;
});
router_.config([
{ path: '/', component: HomeCmp, as: 'Home', data: this.history },
{ path: '/about', component: AboutCmp, as: 'About' }
]);
}
}
如果您打算做一些更复杂的事情,我建议使用服务在 routes/components 之间进行通信。这实际上是我喜欢的方式。
示例服务:
import {Injectable} from 'angular2/angular2';
@Injectable()
export class CarsService {
list1: array<any> = ['a','b','c','d'];
list2: array<any>;
constructor() {
this.list2 = [1,2,3,9,11];
}
}
如何注入服务:
export class Cars {
constructor(cars:CarsService) {
this.cmpList1 = cars.list1;
this.cmpList2 = cars.list2;
}
}
这样您就可以使用该服务进行通信,而无需考虑 parent/child 或其他奇怪的限制。
看起来语法已更改。下面对我有用~Angular4.0.0
HTML(传递路由参数)
<li><a [routerLink]="['/templatecreate',{mode:'New'}]">New Job</a></li>
组件
constructor(private route: ActivatedRoute) { }
ngOnInit() {
this.getTemplate();
this.sub = this.route.params.subscribe(params => { this.id = params['mode'];
console.log("Routing Mode", this.id);
});
}
我认为 Angular2 传递数据的正确方式是通过依赖注入(通过使用服务),否则用户将能够在浏览器 URL 中看到您传递的数据。
此外,使用服务将允许 "Separation of Concerns",这意味着组件 A 不应依赖于组件 B。
依赖注入链接:
1) https://angular.io/guide/dependency-injection
我们有一个很大的 angular 项目(刚从 Angular 开始,所以解决方案与我们的理解一样好:-))。
shell 组件可以调用 4 个(基于路由的)"action" 模块中的任何一个 - 其中每个模块都有自己的服务(但没有组件视图)并且可以调用 6 个中的任何一个(基于路由的)共享组件。共享组件在所有 4 个服务之间共享,因此它们不能有任何特定于调用模块的逻辑。
我们正在使用服务解析器 ActionModuleServiceResolver,它是所有 4 个操作服务的 DI。基于状态 (RouterStateSnapshot) URL,我们 return 相应的服务。
@Injectable()
export class ActionModuleServiceResolver implements Resolve<ActionModuleService> {
constructor(private _mod1: ModOneService,
private _mod2: ModTwoService, private _mod3: ModThreeService,private _mod4: ModFourService) { }
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): ActionModuleService {
if(state.url.includes(`/${ActionModuleType.ModOne}/`))
return this._mod1;
else if(state.url.includes(`/${ActionModuleType.ModTwo}/`))
return this._mod2;
....
else
return null;
}
}
每个动作模块的路由模块像这样路由到共享组件:
const routes: Routes = [
{
path: 'sharedMod1', component: SharedModOneComponent, data: {
title: `ModOne_SharedModOne`,
routeName: 'sharedMod1'
}, resolve: { actionModule: ActionModuleServiceResolver }
},
接下来各SharedModule通过DI获取激活路由,获取调用服务:
//SharedModOne.component.ts
constructor(protected route: ActivatedRoute) {}
ngOnInit() {
this.actionModSvc= this.route.snapshot.data['actionModule'];
this.actionModSvc.getDesignFile(this.route);
}
希望这对某人有所帮助,如果可以改进,请告诉我。
谢谢,
RDV