Angular router:如何将数据传递给延迟加载模块?

时间:2017-07-05 07:16:13

标签: angular lazy-loading angular-routing angular-module angular-router

我的Angular应用程序模块有以下路由路径:

@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属性将一些数据传递到" documents"中的每个路径,因此我可以从路由路径中声明的任何组件中获取它:

例如,我在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();
    }
}

现在我改变了整个应用程序的路由结构,并使用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等所有其他模块执行相同操作。< / p>

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

4 个答案:

答案 0 :(得分:10)

我想我可能会理解这个问题是什么。

问题

以下是提供的吸烟者@smartmouse的路由图。

- home
  - shop
  - contact
    - map
  - about

data路由配置中配置了home个对象。直接子路由可以访问此数据对象。问题是,非直接子map想要访问data对象,但显然,它不能。{/ p>

我们可以知道@smartmouse希望进一步推动 - 嵌套的非直接子路由可以访问来自祖先的数据

为什么不能?

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

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

解决方案

再看看我提供的那个傻瓜。

  

注意:我正在使用的Angular包是v4.3.0

方法#1 - 查询参数

我在home.component.ts中为contact路由定义了一些查询参数。你可以看到如何使用它。

<强>赞成

  • 您可以在任何级别的路径上访问查询参数。
  • 适用于lazyload模块

<强>缺点

  • 您无法在路由配置中定义查询参数。

    但是你可以使用一些路径生命周期钩子为目标祖先路线定义它们

方法#2 - 服务

在作为Singleton Pattern播放的应用程序的顶级上定义数据共享服务。此外,使用一些util来防止它被启动两次。然后你可以在其中放入一些数据,并在任何地方检索它。

<强>赞成

  • 通过DI全局可见;
  • 适用于lazyload模块

<强>缺点

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

方法#3 - 路线解决

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

  

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

以@ smartmouse的plunkr为例。

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

<强>赞成

  • 适用于任何级别的嵌套路由
  • 适用于lazyload模块

<强>缺点

  • 您可能必须在子路由要访问该数据的每个父路由中声明解析属性。这是一种肮脏的工作。

目前,没有完美和通用的解决方案,通常使用Angular。有人应权衡利弊,选择合适的人选。

答案 1 :(得分:5)

您可以使用activatedRoute.pathFromRoot遍历父路由,并从最近的祖先获取数据。这样的事情似乎有效:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>Hello world!</div>

https://plnkr.co/edit/K5Rb1ZvTvSQNM6tOLeFp

答案 2 :(得分: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();
  }
}

答案 3 :(得分:-1)

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

该服务可以具有设置和获取值的功能,因此您可以在服务中使用这些功能来获取所需的数据