在Angular中分享组件?

时间:2018-03-28 07:22:19

标签: angular angular-router

我正在开发一款具有地图的Google Angular应用程序(谷歌地图API)。我希望能够只是移动地图(找到位置),添加标记,编辑现有标记等。我认为最好的行动方案是将每个动作都给自己的子路径,例如

export const routes: Routes = [
   ...
   { 
      path: 'location', 
      component: LocationComponent,
      children: [
         { path: '', redirectTo: 'overview', pathMatch: 'full' },
         { path: 'overview', component: LocationOverviewComponent },
         { path: 'add', component: AddLocationComponent },
      ]
   },
   ...
}

因此,子路径的每个组件都需要访问具有不同行为的地图组件:

  • overview中有一个'+'FAB,但add
  • 中没有
  • 点击add中的地图会添加标记,但不会添加overview
  • ...你得到我的漂移

麻烦的是,任何一个组件都会创建自己的地图实例,这个代价很高,引入了闪烁等。

我的问题是,有没有办法在父路线的组件中初始化地图并将其传递给子路线?或者这种方法无论如何都会被推翻?

2 个答案:

答案 0 :(得分:2)

  

我的问题是,有没有办法可以初始化地图   父路由的组件并将其传递给子路由?

1. 强制初始化

<强> Parent.component.template:

<router-outlet></<router-outlet>>
<map></map> // which costly to initialize

在父级的router-outlet中,子组件将会出现。 你的路由器就像:

/parent/child1 
/parent/child2

使用DI机制,inject可以将任何父组件转移到子级

Chidl1 / Child2类:

class SomeChildComponent{
  constructor(public map: MapComponent){

  }
}

2. 有控制。您可以在父模板上使用多个路由器插座:

  // where child will come
    <router-outlet></router-outlet> 

    // child can fill this outlet with map. Parent also can fill it
    <router-outlet name="map"></router-outlet>

JSFiddle。在这里,当危机中心导航popup组件打开并停留在视图上时,甚至导航到另一条路线,如Heroes

<强>一些-routing.module.ts:

const appRoutes: Routes = [
  {
    path: 'map-route',
    component: MapComponent,
    outlet: 'map'
  },
  {
    path: 'parent-path',
    component: ParentComponent
    children: [
        {
           path: 'child1',
           component: Child1Component               
        },
        {
           path: 'child2',
           component: Child1Component               
        },
    ]

  },
   ...
];

Child1.component.ts:

export class Child1Component { 

  constructor(public router: Router){
       this.router.navigate([{ outlets: { map: 'map-route' }}]);
  }
}

使用多个route-outlet,您可以轻松地从任何子组件控制地图组件(从html添加/删除):

 // to show it
 this.router.navigate([{ outlets: { map: 'map-route' }}]);

// to destroy it
 this.router.navigate([{ outlets: { map: null }}]);

答案 1 :(得分:0)

这就是我要做的事情:

创建一些父路线和一些mapcomponent。在父组件中,您将显示mapcomponent并让您的routeroutlet包含您的子路由。像这样:

<div class="parent">
  <map-component></map-component>
  <router-outlet></router-outlet>
</div>

在此路由器输出中,您可以显示组件及其相关操作(例如,添加,删除)

现在我们创建一个注入mapcomponent和actioncomponents的服务。该服务将保持该州。

export class MapStateService(){
    action: IAction;

    markers: Markers[] = [];
    otherData: OtherData[] = [];
}

现在我们创建一个动作界面,它将由我们的动作组件实现:

interface IAction {
    clickLocation(x: number, y: number);
    otherAction();
}

在我们的actioncomponent的构造函数中,注入stateService并将当前组件设置为action。

export class ActionAddComponent extends IAction implements OnInit{
    constructor(private mapStateService: MapStateService)

    ngOnInit(){
        this.mapStateService.action = this;
    }

    clickLocation(x: number, y: number){
        //Do whatever you want, probably add a marker or so.
        this.mapStateService.markers.push(new Marker(x, y));
    }

    otherAction(){

    }
}

现在,只要在mapcomponent中执行某些操作,就可以从操作界面调用该方法:

export class MapComponent{
    constructor(private mapStateService: MapStateService)

    @HostListener('mousedown', ['$event'])
    onMousedown(event) {
        if(!isNullOrUndefined(this.mapStateService.action){
            this.mapStateService.action.clickLocation(event.x, event.y);
        }
    }
}