Angular 2+可恢复组件

时间:2017-07-19 17:50:44

标签: angular asp.net-core-mvc

最近我在Angular 4中开发了一些可重用的UI组件。意图是这些组件应该可以从CDN获得,这些组件可以在任何Asp.net或Java Web应用程序中使用。当组件发生任何变化时,消费者应用程序应该可以进行更改,而无需更改或编译消费者应用程序。

例如,我使用angular 4 app创建了页眉,页脚和侧边栏组件。我在Web服务器(IIS)上托管了应用程序包。

在另一个应用程序(MVC核心)中,我引用了这些bundle(* .js)文件,并且所有组件的页眉,页脚都呈现完美。

问题: 作为Angular应用程序的一部分,我还开发了一些服务,这些服务使用一些get和set方法角度服务调用与MVC-Core应用程序中的组件进行通信。我无法访问这些服务,相反,我会说当代码托管在Web服务器上时,不知道如何从编译的ES5代码中注入MVC​​应用程序打样代码中的这些服务/模块。 我可能会做一些愚蠢的错误,因为我对棱角4有点新鲜。

body标签内的示例代码:

     <!-- Top Navbar -->
        <my-header></my-header>
        <!-- /Top Navbar -->
        <!--  Sidebar -->
        <my-navsidebar></my-navsidebar>
        <!-- / Sidebar -->
        <!-- Main Content -->
        <section class="content-wrap">
            <!-- Breadcrumb -->
            <!--<asr-breadcrumb ></asr-breadcrumb>-->
            <!-- /Breadcrumb -->
            @RenderBody()
        </section>
        <!-- /Main Content -->
        <!-- Search Bar -->
        <my-searchbar></my-searchbar>

        <!-- /Search Bar -->
        <!-- Chat -->
        <my-notificationbar></my-notificationbar>
        <!-- /Chat -->
        <!-- Footer -->
        <my-footer></my-footer>
        <!-- /Footer -->

        <script type="text/javascript" src="http://server/dist/main.bundle.js"></script>

页脚组件ts文件

    import {Component, OnInit} from '@angular/core';

    @Component({
      // tslint:disable-next-line:component-selector
      selector: 'my-footer',
      templateUrl: './templates/footer.html',
      styleUrls: ['./my-footer.component.css']
    })
    export class MyFooterComponent implements OnInit {
      footerDate: any = new Date();
      constructor() {}

      ngOnInit() {}

    }

页脚html

    <footer class="right-align">{{ footerDate | date :'yyyy'}} 
    <i class="fa fa-copyright"></i> All rights reserved.</footer>

角度应用程序提供的服务之一:

import { Injectable } from '@angular/core';

@Injectable()
export class MyDataserviceService {

  constructor() { }
  log(){
    console.log('from service');
  }

}

提前致谢

2 个答案:

答案 0 :(得分:0)

首先,组件的一个好方法是将每个组件在其自己的模块上分组,并将组件使用的所有服务声明到该模块中。这样,您只需将模块导入到新应用程序的app.module中,它们就可以正常工作。

另一方面,您没有描述这些服务的用途,但请确保您的组件没有耦合,以便您可以重复使用,就像您在其他应用程序中构建块一样。

答案 1 :(得分:0)

注意:这不是Angular特定的

假设我有一个将被多个应用程序使用的组件。无论交付机制(通过CDN或其他),第一步是将这些组件转换为单独的

实际上,有些东西是包的特征。

首先,您可以通过包管理器(例如JSPM,Yarn或NPM)安装包,从CDN下载或通过公司内部特定机制托管主机。

软件包的另一个重要方面是,虽然它通常不是自给自足或独立的,但它通过清单描述了自己的依赖关系。这很关键,因为它允许透明地使用包。对于JavaScript包,这通常意味着该包包含一个package.json文件,该文件列出了这些依赖项,它们所需的semver范围以及其他元数据。

假设您想要一个组件,比如说search-bar并将其放入一个可由多个应用程序安装和引用的包中。此外,假设目前search-bar是其中一个应用程序的一部分,如下所示

// app/components/search-bar.js
import {inject, template} from '@framework/utils';

import SearchService from 'app/services/search-service';

@inject(SearchService)
@template(`<div>....</div>`)
export default class SearchBar {
  constructor(searchService) {
    this.searchService = searchService;
  }
}

现在我们决定将它变成自己的包。

首先,我们将它从app/components移到一个新目录中,让我们称之为packages/search-bar,这在概念上是一个新的独立项目。我们将package.json文件添加到此目录(可能是bower.json之类的其他内容,但这只是一个示例)。该目录现在包含以下

package.json
search-bar.js

package.json看起来像

{
  "name": "search-bar",
  "version": "1.0.0",
  "description": "A shared search bar component used by multiple applications",
  "main": "search-bar.js"
}

现在,我们遇到了第一个障碍,search-bar有一些外部的依赖。这取决于我们用来构建我们的Web应用程序的框架的utils部分中的两个装饰器(我巧妙地命名了这个框架 framework )。这很容易解决。我们只需将package.json更改为

即可
{
  "name": "search-bar",
  "version": "1.0.0",
  "description": "A shared search bar component used by multiple applications",
  "main": "search-bar.js",
  "dependencies": {
    "@framework/utils": "*"
  }
}

这一切都很好但是我们注意到我们还依赖别的东西。作为应用程序的一部分的服务,用于包含新包装的组件本身!

这是它开始变得复杂的地方。由于我们似乎使用依赖注入系统使用函数引用而不是字符串来注册和注入依赖项,因此我们无法使search-bar隐式依赖于search-service。这可能是最好的,因为它是一种绝对可怕的做法!

如果原始应用程序中唯一依赖app/services/search-service的模块是search-bar,那么答案很简单,只需将search-service移到我们正在提取的search-bar包中

但是,如果我们的应用程序的其他部分依赖于它,我们需要创建包含该服务的另一个不同的包。就目前而言,我们将满足于仅仅提取这一单一服务,因此我们最终会得到一些看起来很熟悉的东西

{
  "name": "search-service",
  "version": "1.0.0",
  "description": "A shared search service used by multiple applications",
  "main": "search-service.js",
  "dependencies": {
    "@framework/utils": "*"
  }
}

详细阐述,search-service.js看起来像

// packages/search-service/service-service.js
import {registered} from 'framework/utils';

@registered
export default class SearchService {
  searchFor(searchTerm) {...}
}

现在我们调整search-bar包,如下所示

packages/search-bar/package.json文件:

{
  "name": "search-bar",
  "version": "1.0.0",
  "description": "A shared search bar component used by multiple applications",
  "main": "search-bar.js",
  "dependencies": {
    "@framework/utils": "*",
    "search-service": "^1.0.0"
  }
}

packages/search-bar/search-bar.js文件:

import {inject, template} from '@framework/utils';

// We are now importing from the name of our extracted shared search-service package!
import SearchService from 'search-service';

@inject(SearchService)
@template(`<div>....</div>`)
export default class SearchBar {
  constructor(searchService) {
    this.searchService = searchService;
  }
}

完成上述重组后,原始应用的package.json现在会将"search-service""search-bar"列为依赖关系。

这是一般的想法。现在这些软件包是独立的,每个软件包都列出了自己的依赖项(实际上可能更复杂),它们可以单独构建,发布和部署。

注意:这是一个很好的机会来考虑整个应用程序的体系结构,例如我们可能希望将多个服务或组件提取到一个共享包中。