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

Several pages with the same structure in Angular

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

情况如下:我正在创建一个 CRUD SPA with several "pages" (using routing). Turns out that several of those pages shares the same structure and behaviors, and only differs (visually) from the way the items are rendered in a list and its details when selected. Think like several pages of Asana,其中页面之间的唯一区别是列表和详细信息的渲染方式。

我想为这些页面中的每一个创建一个模块,但是复制并粘贴所有代码只是为了更改一小部分文件(更新也将是一场噩梦)似乎很蹩脚。

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

感谢您的帮助。

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

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

我阅读了有关该工具和动态创建组件等其他内容的信息,但 none 正是我想要的(特别是考虑到学习曲线)。所以,我花了一些时间,但我自己找到了一个(非常疯狂的)解决方案。

首先,我创建了一个基本模块。在其中,我创建了一个 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)创建了一个抽象基础 class。我在依赖注入和使用构造函数中的访问字自动创建变量方面遇到了一些问题,所以我的解决方案如下:

export abstract class AbstractDetailsComponent {
    protected service: BaseService;

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

请注意,我没有使用 @Component 装饰器,因为它将被忽略(在 PageComponent 中也是如此)。另一件事是创建了一些 Base* classes 和接口以确保一致性(如 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 和其中一种样式指向基本模块内的文件。这是我发现在所有页面之间共享相同页面结构的方式。

现在,差距。我需要的两个组件都很相似。基本上,我为每个扩展基础 class 并注入正确的服务。这是 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

我不知道这是否是最好的解决方案,但它确实如我所愿。很难解释我所做的所有步骤(通常这是一个过于复杂的解决方案的标志)但我希望它是可以理解的。