【发布时间】:2016-09-27 16:43:15
【问题描述】:
所以我习惯在 Angular 中使用工厂和服务。
我正在阅读 Angular2 文档,但没有看到任何相当于工厂的东西。 Angular2 的等价物是什么?
【问题讨论】:
所以我习惯在 Angular 中使用工厂和服务。
我正在阅读 Angular2 文档,但没有看到任何相当于工厂的东西。 Angular2 的等价物是什么?
【问题讨论】:
工厂、服务、常量和值都在 Angular2 中消失了。 Angular2 与经典的 Angular 完全不同。在Angular2中,核心概念是
服务、工厂、提供者和常量的想法在 Angular 1 中受到了批评。很难在两者之间做出选择。删除它们会简化一些事情。
在最初的 Angular 中,你会定义一个这样的服务
app.service('BookService', ['$http', '$q', BookService]);
function BookService($http, $q){
var self = this;
var cachedBooks;
self.getBooks = function(){
if (cachedBooks) {
return $q.when(cachedBooks);
}
return $http.get('/books').then(function(response){
cachedBooks = response.data.books;
return cachedBooks;
})
}
}
Angular2 极大地利用了 ES6 语法,使代码更具可读性和易于理解。
ES6 中的一个新关键字是class,可以将其视为一种服务。
ES6 类是基于原型的 OO 模式的简单糖。拥有一个方便的声明形式使类模式更易于使用,并鼓励互操作性。类支持基于原型的继承、超级调用、实例和静态方法以及构造函数。
下面是相同代码在 Angular2 中的样子
import {HttpService, Promise} from '../Angular/Angular2';
export class BookService{
$http, $q, cachedBooks;
constructor($http: HttpService, $q: Promise) {
this.$http = $http;
this.$q = $q
}
getBooks() {
if (this.cachedBooks) {
return this.$q.when(this.cachedBooks);
}
return this.$http.get('/books').then(function(data) {
this.cachedBooks = data.books;
return this.cachedBooks;
})
}
}
【讨论】:
感谢@Richard Hamilton 的回答,除此之外还有几点需要注意。
对于工厂、服务等,在 Angular2 中我们有服务(或共享服务)。我们必须让我们的服务Injectable 才能使用它。
注意:此代码属于 beta 版本,不是 RC。
import {Component, Injectable,Input,Output,EventEmitter} from 'angular2/core'
import {Router} from 'angular2/router';
import {Http} from 'angular2/http';
export interface ImyInterface {
show:boolean;
}
@Injectable() <---------------------------- Very Important
export class sharedService { <----------------- Service Name
showhide:ImyInterface={show:true};
constructor(http:Http;router:Router)
{
this.http=http;
}
change(){
this.showhide.show=!this.showhide.show;
}
}
如果我想在我的应用程序的任何地方使用,那么我必须像这样在引导函数中注入这个服务,
bootstrap(App, [HTTP_PROVIDERS,sharedService <--------Name Injection
ROUTER_PROVIDERS,bind(APP_BASE_HREF).toValue(location.pathname)
]);
这样,它会创建您的服务的单个实例。如果您不想使用单实例,您可以做的是 - 您可以在 @component 装饰器中使用 Providers:[sharedService] 元数据。
然后,在您的组件之一中使用它,
export class TheContent {
constructor(private ss: sharedService) { <--------Injection dependency of your newly created service
console.log("content started");
}
showhide() {
this.ss.change(); <----- usage
}
}
【讨论】:
bind(...).toXxx(...) 是不推荐使用的语法。改用provide(..., {useXxx: ...})
我不知道工厂在 Angular1 中究竟做了什么,但在 Angular2 中有 useFactory:
{
provide: SomeClass,
useFactory: (dep1, dep2) => (x) => new SomeClassImpl(x, dep1, dep2),
deps: [Dep1, Dep2]
}
如果默认值不符合您的需求,则提供您自己的实例构造逻辑。
您也可以自己注入工厂来创建新实例:
/* deprecated or removed depending on the Angular version you are using */
provide(SomeClass, {
useFactory: (dep1, dep2) => {
(x) => new SomeClassImpl(x, dep1, dep2),
},
deps: [Dep1, Dep2]
})
constructor(@Inject(SomeClass) someClassFactory: any) {
let newSomeClass = someClassFactory(1);
}
参数 x 必须有类型赋值,否则 angular 不知道如何处理。
class SomeClassImpl {
constructor(x: number, dep1: Dep1, dep2: Dep2){}
}
【讨论】:
let newSomeClass = someClassFactory(1);(中间剪断) - 在 CTOR 中,someClassFactory: any 已经(!)调用,已经返回 new SomeClassImpl。那么你为什么在let newSomeClass = someClassFactory(1); 中再次调用它呢?我错过了什么吗?
(x) =>。目的是注入工厂函数,而不是工厂函数的结果。
如果您需要某个组件中的服务的新实例,您需要在该组件中提供它,如下所示:
@Component({
selector: 'hero-list',
templateUrl: './hero-list.component.html',
providers: [ HeroService ]
})
这将像工厂一样生成HereService 的新实例。
【讨论】: