Angular中具有相同结构的几个页面

时间:2017-05-12 19:48:40

标签: angular typescript single-page-application angular-module

我对Angular相对较新,我正努力使用通用模块为多个页面创建相同的行为。

情况如下:我正在创建一个CRUD SPA,其中包含多个"页面" (使用路由)。事实证明,这些页面中的一些页面共享相同的结构和行为,并且仅在视觉上与列表中的项目呈现方式(选择时的详细信息)不同。想象几页Asana,其中页面之间的唯一区别是列表和细节是渲染器的方式。

我正在考虑为每个页面创建一个模块,但复制和粘贴所有代码只是为了改变一小部分文件似乎很蹩脚(更新也会是一场噩梦)。

我试图实现的解决方案是创建一个主CRUD模块,其中包含一个Component / html / css,我可以通过某种方式参数化每个页面使用哪个渲染器。或者任何其他具有最小复制粘贴的解决方案。

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

我读过关于工具和其他一些东西,比如动态创建的组件,但没有一个是我想要的(特别是考虑学习曲线)。所以,我花了一些时间,但我自己找到了一个(非常疯狂的)解决方案。

首先,我创建了一个基本模块。在其中,我创建了一个PageComponent来调用我需要的页面的两个部分:一个用于列表,另一个用于详细信息(如Asana)。 page.component.html模板如下所示:

<div class="mdl-grid">
    <div class="mdl-cell mdl-cell--8-col">
        <app-list></app-list>
    </div>
    <div class="mdl-cell mdl-cell--4-col">
        <app-details></app-details>
    </div>
</div>`

在这个基本模块中,我为我需要的每个组件创建了一个抽象基类(AbstractListComponentAbstractDetailsComponent)。我在构造函数中使用访问词创建了依赖注入和自动变量创建的一些问题,所以我的解决方案如下:

export abstract class AbstractDetailsComponent {
    protected service: BaseService;

    protected constructor(service: BaseService) {
        this.service = service;
    }
}

请注意,我没有使用@Component装饰器,因为它会被忽略(在PageComponent中也是如此)。另一件事是创建了一些Base*类和接口以确保一致性(如BaseService)。

如您所见,PageComponent <app-list><app-details>请求时,没有人会回答。这里开始疯狂的部分。

对于每个页面,我创建了一个模块,并在其中填充了填补空白的组件。此外,页面的主要组件扩展PageComponent。例如,在我的应用中,我有一个“技能”页面,该页面会显示以下SkillsComponent

@Component({
    selector: 'skills-page', // doesn't really matter, this will be called by the router
    templateUrl: '../base-module/page.component.html',
    styleUrls: [ '../base-module/page.component.css', './skills.component.css' ]
})
export class SkillsComponent extends PageComponent { }

请注意,templateUrl和其中一个样式指向基本模块内的文件。这是我发现在所有页面之间共享相同页面结构的方式。

现在,差距。我需要的两个组件都是相似的。基本上,我为每个扩展基类并注入正确的服务。这是SkillDetailsComponent

@Component({
    selector: 'app-details', // <-- the name required by the PageComponent template
    templateUrl: './skill-details.component.html',
    styleUrls: [ '../base-module/details.component.css', './skills-details.component.css' ]
})
export class SkillsDetailsComponent extends DetailsComponent {
    public constructor(service: SkillsService) {
        super(service);
    }
}

selector正好是page.component.html所需的app/ ├ base-module/ │ ├ base.component.css │ ├ base.component.html │ ├ base.component.ts │ ├ base.module.ts │ ├ details.component.css │ ├ details.component.ts │ ├ list.component.css │ ├ list.component.html │ └ list.component.ts └ skills-module/ ├ skills-details.component.css ├ skills-details.component.ts ├ skills-list.component.css ├ skills-list.component.ts ├ skills.component.css ├ skills.component.html ├ skills.component.ts └ skills.module.ts 。所有页面的所有列表和详细信息组件共享相同的方法。这使得相同的模板在所有页面中都很有用,因为选择器是相同的。

另一件事是构造函数。我不得不这样做才能注入正确的服务。

最终的文件结构如下所示:

url = git@github.com:/username/repository.git

我不知道它是否是最好的解决方案,但它就像我需要的一样。我很难解释我所做的所有步骤(通常这是一个太复杂的解决方案的标志),但我希望这是可以理解的。

答案 1 :(得分:0)

我的猜测是你正在使用ng-route。尝试查看ui-router https://github.com/angular-ui/ui-router

UI-Router是事实上标准的AngularJS客户端路由框架,支持嵌套视图。 UI-Router背后的概念是将视图建模为状态的分层树。