使用适当的更改跟踪将服务 属性 绑定到组件 属性
Bind a service property to a component property with proper change tracking
考虑完全简单的 Angular2 服务:
import { Injectable } from '@angular/core';
import {Category} from "../models/Category.model";
@Injectable()
export class CategoryService {
activeCategory: Category|{} = {};
constructor() {};
}
然后是使用该服务的组件:
import { Component, OnInit } from '@angular/core';
import {CategoryService} from "../shared/services/category.service";
import {Category} from "../shared/models/Category.model";
@Component({
selector: 'my-selector',
template: `
{{categoryService.activeCategory.Name}}<br/>
{{category.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
category:Category|{} = {};
constructor(public categoryService:CategoryService){};
ngOnInit() {
this.category = this.categoryService.activeCategory;
};
}
假设适当定义了类别模型,并假设某个地方的另一个组件在某个时候将服务上的 activeCategory 设置为有效类别。假设类别服务被设置为适当更高级别的提供者。
发生这种情况时,模板中的第一行将正确显示类别名称,但第二行不会。我尝试过在服务上使用 getter 和 setter 与原始访问;我尝试过原始类型与对象与对象属性;我无法相信第一行是此类访问的合适范例。有人能告诉我将服务 属性 绑定到组件 属性 的最简单方法,该方法将在 angular 两次中正确地进行更改跟踪吗?
澄清:我知道我可以使用我自己创建和推送的可观察对象。我要问的是,是否有任何一种已经嵌入到框架中的方法(不需要我为可观察对象编写大量样板文件),它只是在服务和组件之间建立了可变轨道.
Observable
s 可以在没有太多样板的情况下使用 Behavior
s.
@Injectable()
export class CategoryService {
activeCategory:BehaviorSubject<{category:Category}> = new BehaviorSubject({category:null});
// or just `Subject` depending on your requirements
}
@Component({
selector: 'my-selector',
template: `
{{(categoryService.activeCategory | async)?.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
constructor(public categoryService:CategoryService){};
}
您也可以只绑定到服务的属性
@Component({
selector: 'my-selector',
template: `
{{categoryService?.activeCategory?.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
constructor(public categoryService:CategoryService){};
}
使用 Elvis(或安全导航)运算符,如果 activeCategory
稍后才获取值,例如当异步调用完成时,您不会收到错误消息。
样板块不是太大。
但是这里发生的事情是,当服务被创建或者你拨打电话时,你想如何处理它。您的组件将通过订阅了解它,然后将您的本地变量更新为新值。允许您以 this.activeCategory.
的形式访问它
import { Injectable } from '@angular/core';
import {Category} from "../models/Category.model";
import {Subscription} from 'rxjs/Subscription';
@Injectable()
export class CategoryService {
private _categoryObject = new Subject<any>();
categoryObjectAnnounced$ = this._categoryObject;
private _activeCategoryObject = new Subject<any>();
activeCategoryObjectAnnounced$ = this._activeCategoryObject;
activeCategory: Category|{} = {};
constructor() {};
}
import { Component, OnInit } from '@angular/core';
import {CategoryService} from "../shared/services/category.service";
import {Category} from "../shared/models/Category.model";
import {Subscription} from 'rxjs/Subscription';
@Component({
selector: 'my-selector',
template: `
{{activeCategory.Name}}<br/>
{{category.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
category:Category|{} = {};
activeCategory:ActiveCategory|{} = {};
activeCategorySubscription : Subscription;
categorySubscription : Subscription;
constructor(public categoryService:CategoryService){
this.categorySubscription= this.categoryService.categoryObjectAnnounced$.subscribe((category) => {
this.category= category;
});
this.activeCategorySubscription= this.categoryService.activeCategoryObjectAnnounced$.subscribe((active) => {
this.activeCategory= active;
});
};
ngOnInit() {
};
}
您可以尝试将 ngOnInit()
替换为 ngDoCheck()
。我不确定(实际上我怀疑)这是正确的做法,无论如何你可以尝试。
这种方法在每个变化检测周期都是 运行(而不是我猜的标准 Angular 算法,这是潜在的问题)因此你应该 category
MySelectorComponent
的 属性 更新了服务的变化。
再次需要注意副作用(我不清楚)。
考虑完全简单的 Angular2 服务:
import { Injectable } from '@angular/core';
import {Category} from "../models/Category.model";
@Injectable()
export class CategoryService {
activeCategory: Category|{} = {};
constructor() {};
}
然后是使用该服务的组件:
import { Component, OnInit } from '@angular/core';
import {CategoryService} from "../shared/services/category.service";
import {Category} from "../shared/models/Category.model";
@Component({
selector: 'my-selector',
template: `
{{categoryService.activeCategory.Name}}<br/>
{{category.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
category:Category|{} = {};
constructor(public categoryService:CategoryService){};
ngOnInit() {
this.category = this.categoryService.activeCategory;
};
}
假设适当定义了类别模型,并假设某个地方的另一个组件在某个时候将服务上的 activeCategory 设置为有效类别。假设类别服务被设置为适当更高级别的提供者。
发生这种情况时,模板中的第一行将正确显示类别名称,但第二行不会。我尝试过在服务上使用 getter 和 setter 与原始访问;我尝试过原始类型与对象与对象属性;我无法相信第一行是此类访问的合适范例。有人能告诉我将服务 属性 绑定到组件 属性 的最简单方法,该方法将在 angular 两次中正确地进行更改跟踪吗?
澄清:我知道我可以使用我自己创建和推送的可观察对象。我要问的是,是否有任何一种已经嵌入到框架中的方法(不需要我为可观察对象编写大量样板文件),它只是在服务和组件之间建立了可变轨道.
Observable
s 可以在没有太多样板的情况下使用 Behavior
s.
@Injectable()
export class CategoryService {
activeCategory:BehaviorSubject<{category:Category}> = new BehaviorSubject({category:null});
// or just `Subject` depending on your requirements
}
@Component({
selector: 'my-selector',
template: `
{{(categoryService.activeCategory | async)?.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
constructor(public categoryService:CategoryService){};
}
您也可以只绑定到服务的属性
@Component({
selector: 'my-selector',
template: `
{{categoryService?.activeCategory?.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
constructor(public categoryService:CategoryService){};
}
使用 Elvis(或安全导航)运算符,如果 activeCategory
稍后才获取值,例如当异步调用完成时,您不会收到错误消息。
样板块不是太大。 但是这里发生的事情是,当服务被创建或者你拨打电话时,你想如何处理它。您的组件将通过订阅了解它,然后将您的本地变量更新为新值。允许您以 this.activeCategory.
的形式访问它import { Injectable } from '@angular/core';
import {Category} from "../models/Category.model";
import {Subscription} from 'rxjs/Subscription';
@Injectable()
export class CategoryService {
private _categoryObject = new Subject<any>();
categoryObjectAnnounced$ = this._categoryObject;
private _activeCategoryObject = new Subject<any>();
activeCategoryObjectAnnounced$ = this._activeCategoryObject;
activeCategory: Category|{} = {};
constructor() {};
}
import { Component, OnInit } from '@angular/core';
import {CategoryService} from "../shared/services/category.service";
import {Category} from "../shared/models/Category.model";
import {Subscription} from 'rxjs/Subscription';
@Component({
selector: 'my-selector',
template: `
{{activeCategory.Name}}<br/>
{{category.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
category:Category|{} = {};
activeCategory:ActiveCategory|{} = {};
activeCategorySubscription : Subscription;
categorySubscription : Subscription;
constructor(public categoryService:CategoryService){
this.categorySubscription= this.categoryService.categoryObjectAnnounced$.subscribe((category) => {
this.category= category;
});
this.activeCategorySubscription= this.categoryService.activeCategoryObjectAnnounced$.subscribe((active) => {
this.activeCategory= active;
});
};
ngOnInit() {
};
}
您可以尝试将 ngOnInit()
替换为 ngDoCheck()
。我不确定(实际上我怀疑)这是正确的做法,无论如何你可以尝试。
这种方法在每个变化检测周期都是 运行(而不是我猜的标准 Angular 算法,这是潜在的问题)因此你应该 category
MySelectorComponent
的 属性 更新了服务的变化。
再次需要注意副作用(我不清楚)。