typescript Angular 2.3 组件继承和依赖注入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41560550/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 2.3 Component Inheritance and Dependency Injection
提问by David Cruwys
How can I share dependency injection between child and parent components with the new Angular 2.3 Component Inheritance.
如何使用新的 Angular 2.3 组件继承在子组件和父组件之间共享依赖注入。
e.g. I want to move AlertService down into the parent component and leave TraingCompanyService in the derived component
例如,我想将 AlertService 向下移动到父组件中,并将 TraingCompanyService 留在派生组件中
Current Component
当前组件
@Component({
selector: 'wk-training-company-edit',
template: require('./edit.html')
})
export class TrainingCompanyEditComponent implements OnInit, OnDestroy {
constructor(
private alert: AlertService,
private trainingCompanyService: TrainingCompanyService
) {
}
}
Refactored Components (V1)
重构组件 (V1)
Super must be called before calling this in the constructor of the derived class
在派生类的构造函数中调用 this 之前必须先调用 super
@Component({
selector: 'wk-training-company-edit',
template: require('./edit.html')
})
export class TrainingCompanyEditComponent extends BaseAdminEditComponent implements OnInit, OnDestroy {
constructor(
private alert: AlertService,
private trainingCompanyService: TrainingCompanyService
) {
// Error: Super must be called before calling this in the constructor of the derived class
super(this.alert);
}
}
export class BaseAdminEditComponent {
constructor(private alert: AlertService) {
}
protected handleSaveError(error: any) {
if (error.message) {
if (error.errors && _.isArray(error.errors) && error.errors.length > 0) {
this.alert.error(_.join(error.errors, '\n'), error.message);
}
else {
this.alert.error(error.message);
}
}
}
}
Refactored Components (V2)
重构组件 (V2)
Class TrainingCompanyEditComponent incorrectly extends base class BaseAdminEditComponent, types have seperate declarations of private property 'alert'
类 TrainingCompanyEditComponent 错误地扩展了基类 BaseAdminEditComponent,类型具有私有属性“警报”的单独声明
@Component({
selector: 'wk-training-company-edit',
template: require('./edit.html')
})
export class TrainingCompanyEditComponent extends BaseAdminEditComponent implements OnInit, OnDestroy {
// Class TrainingCompanyEditComponent incorrectly extends base class BaseAdminEditComponent, types have seperate declarations of private property 'alert'
constructor(
private alert: AlertService,
private trainingCompanyService: TrainingCompanyService
) {
// alert instead of this.alert
super(alert);
}
}
export class BaseAdminEditComponent {
constructor(private alert: AlertService) {
}
protected handleSaveError(error: any) {
if (error.message) {
if (error.errors && _.isArray(error.errors) && error.errors.length > 0) {
this.alert.error(_.join(error.errors, '\n'), error.message);
}
else {
this.alert.error(error.message);
}
}
}
}
Refactored Components (V3)
重构组件 (V3)
This works, just wondering if it is the best technique
这有效,只是想知道这是否是最好的技术
@Component({
selector: 'wk-training-company-edit',
template: require('./edit.html')
})
export class TrainingCompanyEditComponent extends BaseAdminEditComponent implements OnInit, OnDestroy {
// Class TrainingCompanyEditComponent incorrectly extends base class BaseAdminEditComponent, types have seperate declarations of private property 'alert'
constructor(
private alert: AlertService,
private trainingCompanyService: TrainingCompanyService
) {
// alert instead of this.alert
super(alert);
}
}
export class BaseAdminEditComponent {
// Create a private variable with a different name, e.g. alert2
private alert2: AlertService;
constructor(alert: AlertService) {
this.alert2 = alert;
}
protected handleSaveError(error: any) {
if (error.message) {
if (error.errors && _.isArray(error.errors) && error.errors.length > 0) {
this.alert2.error(_.join(error.errors, '\n'), error.message);
}
else {
this.alert2.error(error.message);
}
}
}
}
采纳答案by David Cruwys
I finally worked out the pattern that works, it is important to not use the private (syntacting suger pattern) that Radim mentioned in the constructors.
我终于找到了有效的模式,重要的是不要使用 Radim 在构造函数中提到的私有(语法糖模式)。
I made the alert service a protected property on the base class.
我将警报服务设为基类的受保护属性。
And it is important to bind the base event handler to this handlerSaveError.bind(this)
将基本事件处理程序绑定到此很重要 handlerSaveError.bind(this)
Final working code is here.
最终工作代码在这里。
Base Class
基类
import * as _ from "lodash";
import {AlertService} from '../common/alert/alert.service';
export class BaseAdminEditComponent {
protected alert: AlertService;
constructor(alert: AlertService) {
this.alert = alert;
}
protected handleSaveError(error: any) {
if (error.message) {
if (error.errors && _.isArray(error.errors)) {
console.error(error.errors);
}
this.alert.error(error.message);
}
}
}
Component Instance Class
组件实例类
@Component({
selector: 'wk-training-company-edit',
template: require('./edit.html')
})
export class TrainingCompanyEditComponent extends BaseAdminEditComponent {
trainingCompany: TrainingCompany;
trainingCompanyId: number;
constructor(alert: AlertService, // Don't use private property
private validation: ValidationService,
private trainingCompanyService: TrainingCompanyService) {
super(alert);
// Other Constructor Code Here
}
onSave($event) {
console.log('Save TrainingCompany');
this.trainingCompany = TrainingCompany.fromJson(this.form.value);
console.log(JSON.stringify(this.trainingCompany, null, 2));
var isNew = _.isNil(this.trainingCompany.id);
this.trainingCompanyService
.upsert$(this.trainingCompany)
.subscribe((response: EntityResponse<TrainingCompany>) => {
try {
this.alert.success('TrainingCompany updated');
this.modelChange.fire('training-company', isNew ? 'new' : 'update', this.trainingCompany);
}
catch (e) {
console.error(e);
throw e;
}
}, this.handleSaveError.bind(this)); // Common Error Handler from base class. NOTE: bind(this) is required
}
}
回答by Jonesy
Just set the access modifier of the constructor parameter in the derived class at the same level as that in the base class. i.e.
只需在派生类中将构造函数参数的访问修饰符设置在与基类中相同的级别即可。IE
Base Class
基类
import * as _ from "lodash";
import {AlertService} from '../common/alert/alert.service';
export class BaseAdminEditComponent {
constructor(protected alert: AlertService) { }
protected handleSaveError(error: any) {
if (error.message) {
if (error.errors && _.isArray(error.errors)) {
console.error(error.errors);
}
this.alert.error(error.message);
}
}
}
Derived Class
派生类
@Component({
selector: 'wk-training-company-edit',
template: require('./edit.html')
})
export class TrainingCompanyEditComponent extends BaseAdminEditComponent {
trainingCompany: TrainingCompany;
trainingCompanyId: number;
constructor(
protected alert: AlertService,
private validation: ValidationService,
private trainingCompanyService: TrainingCompanyService) {
super(alert);
// Other Constructor Code Here
}
}
回答by Radim K?hler
The constructor definition with modifier keywords like this
带有修饰符关键字的构造函数定义如下
export class TrainingCompanyEditComponent
extends BaseAdminEditComponent implements OnInit, OnDestroy {
constructor(
private alert: AlertService,
private trainingCompanyService: TrainingCompanyService
) {
}
...
is just a syntactic sugar for more verbose:
只是更详细的语法糖:
export class TrainingCompanyEditComponent
extends BaseAdminEditComponent implements OnInit, OnDestroy {
private alert: AlertService,
private trainingCompanyService: TrainingCompanyService
constructor(
alert: AlertService,
trainingCompanyService: TrainingCompanyService
) {
this.alert = alert; // assign incoming value to member
this.trainingCompanyService = trainingCompanyService;
}
...
So, this is on the background. And we can do that assignment only once super was called.. that's why we have to change a call using this.alert
(access to member)into alert
(passing the incoming value)
所以,这是背景。并且我们只能在调用 super 后执行该分配.. 这就是为什么我们必须将调用使用this.alert
(访问成员)更改为alert
(传递传入值)
constructor(
private alert: AlertService,
private trainingCompanyService: TrainingCompanyService
) {
//super(this.alert);
super(alert); // this.alert was not assign yet
// next ?
// the this.alert will be assigned for us...
}
Play with this adjusted definition here
回答by dongsj
try to move constructor into BaseAdminEditComponent ,and not override constructor in TrainingCompanyEditComponent.
尝试将构造函数移动到 BaseAdminEditComponent 中,而不是覆盖 TrainingCompanyEditComponent 中的构造函数。
@Component({
selector: 'wk-training-company-edit',
template: require('./edit.html')
})
export class TrainingCompanyEditComponent extends BaseAdminEditComponent implements OnInit, OnDestroy {
}
export class BaseAdminEditComponent {
constructor(private alert: AlertService,
private trainingCompanyService: TrainingCompanyService) {
}
protected handleSaveError(error: any) {
if (error.message) {
if (error.errors && _.isArray(error.errors) && error.errors.length > 0) {
this.alert.error(_.join(error.errors, '\n'), error.message);
}
else {
this.alert.error(error.message);
}
}
}
}