12

我有我的角度应用程序的模块下面的路由路径:Angular router:如何将数据传递给延迟加载模块?

@NgModule({ 
    imports: [ 
     RouterModule.forChild([ 
      { 
       path: 'documents', 
       data: { myObject: MyConstants.OPTION_ONE }, 
       children: [ 
        { 
         path: ':ID_DOC', 
         children: [ 
          { path: 'edit', component: EditDocumentComponent }, 
          { path: '', component: DocumentDetailsComponent }, 
         ] 
        }, 
        { path: 'add', component: AddDocumentComponent }, 
        { path: '', component: DocumentsListComponent } 
       ] 
      } 
     ]) 
    ], 
    exports: [ 
     RouterModule 
    ] 
}) 

export class DocumentsManagementRoutingModule { 
} 

正如你可以看到我用data属性来传递“文件”的一些数据,以每一条路径,所以我可以从任何得到它在路由路径声明的组成部分:

例如,下面是我如何DocumentDetailsComponent获取数据:

export class DocumentDetailsComponent implements OnDestroy { 
    private obsData: Subscription; 
    private option: any; 

    constructor(private route: ActivatedRoute) { 
     this.obsData = this.route.data.subscribe(data => { 
      this.option = data['myObject']; 
     }); 
    } 

    ngOnDestroy(): void { 
     this.obsData.unsubscribe(); 
    } 
} 

现在我改变了整个应用程序的路由结构,我称之为一个bove模块从其他模块进行延迟加载,使用loadChildren属性。我以同样的方式传递数据:

@NgModule({ 
    imports: [ 
     RouterModule.forChild([ 
      { 
       path: 'users', 
       loadChildren: 'app/documents/documents.module#DocumentsModule', 
       data: { myObject: MyConstants.OPTION_ONE }}, 
      { 
       path: ':ID_USER', 
       children: [ 
        { path: 'edit', component: EditUserComponent }, 
        { path: '', component: UserDetailsComponent }, 
       ] 
      }, 
      { path: 'add', component: AddUserComponent }, 
      { path: '', component: UserListComponent } 
     ]) 
    ], 
    exports: [ 
     RouterModule 
    ] 
}) 

export class UsersManagementRoutingModule { 
} 

,我做了所有调用DocumentsManagementRoutingModule其他模块一样,改变myObject财产MyConstants.OPTION_TWOMyConstants.OPTION_THREE等,根据我的需求。

然后,由于我不知道调用我的懒加载模块的模块及其相关路径,如何从调用者模块获取data属性?

+0

https://stackoverflow.com/questions/44796671/pass-parameter-into-modules – Gambo

+0

的可能DUP在我的情况下使用一个懒惰的加载模块是强制的 – smartmouse

+0

@smartmouse有一行'r.url.lastIndexOf(“/”));'非法。 –

回答

2

您可以使用activatedRoute.pathFromRoot遍历父路由,并从最近的祖先获取数据。像这样的东西似乎工作:

ngOnInit(): void { 
    let idx = this.activatedRoute.pathFromRoot.length - 1; 
    while(this.sharedData == null && idx > 0){ 
     this.sub = this.activatedRoute.pathFromRoot[idx].data.subscribe(subData => { 

     if(subData.id) 
      this.sharedData = subData; 

     console.log('shared data', this.sharedData); 
     }); 
     idx--; 
    } 
    } 

https://plnkr.co/edit/K5Rb1ZvTvSQNM6tOLeFp

+0

是的,我喜欢你的解决方案。无论如何,我无法弄清楚为什么我必须循环所有'ActivatedRoute'而不是直接访问currect激活的路径来获取'data'(或'params')我需要... – smartmouse

+1

它似乎是预期的行为https://github.com/angular/angular/issues/12767#issuecomment-260493205 – rusmus

+0

向上移动是一种肮脏,有没有取消订阅操作的内存泄漏。 –

-1

为什么不使用服务来共享模块或任何组件之间的数据。您可以将此服务导入主模块提供程序,因此可以用于所有其他模块(延迟加载模块)并共享数据。

服务可以有函数来设置和获取值,因此你可以利用这些功能在服务得到您所需要的数据

+0

如果我使用共享服务,它只有在您没有通过直接url进入延迟加载模块时才有效。如果您转到属于延迟加载模块的页面,而该页面没有通过将数据发送到共享服务的前一个模块进行传递,则无法获取数据! – smartmouse

+1

是的,我现在明白你的问题。 – Kowsalya

9

我想我可以理解什么是问题是问。


问题

这里是所提供的plunker @smartmouse的路由图。

- home 
    - shop 
    - contact 
    - map 
    - about 

上有home路线配置构成的data对象。直接的子路由可以访问这个数据对象。问题是,非直接子map想访问data对象,但显然,它不能。

我们可以知道@smartmouse希望推得更远 - 嵌套的非直接子路由可以访问来自祖先的数据。

为什么它不能?

查看我修改过的plunker。 https://plnkr.co/edit/FA7mGmspUXHhU8YvgDpT

您可以看到我为contact定义了一个额外的子组件DefaultComponent。它显示它是路线contact的直接和默认子节点,可以解释为它也是上级路线home的直接子节点。因此,它可以访问data对象。

解决方案

看看我再次提供的掠夺者。

注:我使用的角度包是V4.3.0

方法#1 - 查询参数

我定义一些查询参数在home.component.tscontact路线。你可以看到如何使用它。

优点

  • 可以跨路由的任何级别的访问查询参数。

    • 你不能在航线配置定义查询参数:

    • 与lazyload模块

    缺点效果很好。

    但是你可以使用一些路线的生命周期挂钩,以确定他们的目标祖先路线

方法2 - 服务

上的顶级定义数据共享服务应用程序扮演单身模式。另外,使用一些util来防止它被启动两次。然后你可以放入一些数据,并在任何地方找回。

优点

  • 全球可见通过DI;
  • 与lazyload模块

缺点效果很好:

  • 在航线配置无法更新数据。
  • 你必须在其他地方定义数据。如果你无法控制它的来源,这可能是一个问题。

方法3 - 路线的决心

有人可能会发现我也是在plunker定义resolve示例代码。它表明它在路由配置中具有与data相同的行为,除了它实际上用于动态数据检索。

https://vsavkin.com/angular-router-understanding-router-state-7b5b95a12eab#5400
数据属性用于传递一个固定对象到激活路由。它在应用程序的整个生命周期中都不会改变。 resolve属性用于动态数据。

以@ smartmouse的plunkr为例。

我们在'home'路由配置中定义了data。我们可以在ContactModule中为联系人的默认路由定义一个数据解析器,并代理从上级路由传递的数据。然后它的所有直接子路由都可以访问解析的数据对象。

优点

  • 作品以及嵌套路线的任何级别
  • 作品以及与lazyload模块

缺点

  • 您可能需要宣布解决每个父路由中的子路径想要访问该数据的属性。这是一种肮脏的工作。

没有完美的和通用的解决方案,现在,随着角度共同使用。有人应该权衡利弊,并选择适当的。

+0

我想你已经发布了一个错误的Plunker链接...无论如何,当我弄清楚,如果一个直接的孩子在路由器路径中有'component',它可以看到'data'属性,但它会吃掉它,然后禁止它的子节点。那就是问题所在。 – smartmouse

+0

我很抱歉,现在就修复它。 –

+0

@ e-cloud您可否详细说明“方法1缺点:但您可以使用一些路由生命周期钩子为目标祖先路由定义它们” – JGFMK

0
@NgModule({ 
    imports: [ 
     RouterModule.forChild([ 
      { 
       path: 'users', 
       loadChildren: 'app/documents/documents.module#DocumentsModule', 
       resolve : { 
        data: DataResolver 
       } 
      { 
     ]) 
    ], 
    exports: [ 
     RouterModule 
    ] 
}) 

export class UsersManagementRoutingModule { 
} 


@Injectable() 
export class DataResolverimplements Resolve<Data> { 
    resolve() { 
    return this.serice.getData(); 
    } 
} 
+0

这对任何人都适用?我也在尝试这种方法,但延迟加载模块的默认组件永远不会被调用。 –

相关问题