Angular 通过正确的更改跟踪将服务属性绑定到组件属性
考虑一下非常简单的Angular 2服务:Angular 通过正确的更改跟踪将服务属性绑定到组件属性,angular,angular2-services,Angular,Angular2 Services,考虑一下非常简单的Angular 2服务: import { Injectable } from '@angular/core'; import {Category} from "../models/Category.model"; @Injectable() export class CategoryService { activeCategory: Category|{} = {}; constructor() {}; } 然后是使用此服务的组件: import { Co
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;
};
}
从'@angular/core'导入{Component,OnInit};
从“./shared/services/category.service”导入{CategoryService};
从“./shared/models/Category.model”导入{Category};
@组成部分({
选择器:“我的选择器”,
模板:`
{{categoryService.activeCategory.Name}
{{category.Name}}
`,
})
导出类MySelectorComponent实现OnInit{
类别:类别{}={};
构造函数(公共categoryService:categoryService){};
恩戈尼尼特(){
this.category=this.categoryService.activeCategory;
};
}
假设适当定义的类别模型,并假设另一个组件在某处将服务上的activeCategory设置为某个有效类别。假设categoryservice被设置为适当更高级别的提供者
发生这种情况时,模板中的第一行将正确显示类别名称,但第二行不会。我尝试过在服务上使用getter和setter,而不是原始访问;我尝试过基本类型、对象和对象属性;我不相信第一行是这种访问的合适范例。有人能告诉我将服务属性绑定到组件属性的最简单方法吗?这两种方法可以正确地进行更改跟踪
澄清:我知道我可以使用我自己创建和推动的观察结果。我想问的是,是否有任何一种已经融入到框架中的方法(这不需要我为一个可观察的对象编写大量的样板文件)能够在服务和组件之间形成一个可变的轨迹。
可观察的
s可以在没有太多样板文件的情况下使用行为
s
@Injectable()
export class CategoryService {
activeCategory:BehaviorSubject<{category:Category}> = new BehaviorSubject({category:null});
// or just `Subject` depending on your requirements
}
@Injectable()
导出类类别服务{
activeCategory:BehaviorSubject=新的BehaviorSubject({category:null});
//或者只是“主题”,取决于你的要求
}
@组件({
选择器:“我的选择器”,
模板:`
{(categoryService.activeCategory | async)?.Name}
`,
})
导出类MySelectorComponent实现OnInit{
构造函数(公共categoryService:categoryService){};
}
您还可以只绑定到服务的属性
@Component({
selector: 'my-selector',
template: `
{{categoryService?.activeCategory?.Name}}<br/>
`,
})
export class MySelectorComponent implements OnInit {
constructor(public categoryService:CategoryService){};
}
@组件({
选择器:“我的选择器”,
模板:`
{{categoryService?.activeCategory?.Name}
`,
})
导出类MySelectorComponent实现OnInit{
构造函数(公共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() {
};
}
从'@angular/core'导入{Injectable};
从“./models/Category.model”导入{Category};
从'rxjs/Subscription'导入{Subscription};
@可注射()
导出类类别服务{
private _categoryObject=新主题();
categoryObject宣布$=此。_categoryObject;
private _activeCategoryObject=新主题();
activeCategoryObject宣布$=此。\u activeCategoryObject;
活动类别:类别{}={};
构造函数(){};
}
从“@angular/core”导入{Component,OnInit};
从“./shared/services/category.service”导入{CategoryService};
从“./shared/models/Category.model”导入{Category};
从'rxjs/Subscription'导入{Subscription};
@组成部分({
选择器:“我的选择器”,
模板:`
{{activeCategory.Name}}
{{category.Name}}
`,
})
导出类MySelectorComponent实现OnInit{
类别:类别{}={};
activeCategory:activeCategory{}={};
activeCategorySubscription:订阅;
类别认购:认购;
构造函数(公共类别服务:类别服务){
this.categorySubscription=this.categoryService.categoryObject.subscribe((category)=>{
这个。类别=类别;
});
this.activeCategorySubscription=this.categoryService.ActiveCategoryObject已宣布$.subscribe((活动)=>{
this.activeCategory=active;
});
};
恩戈尼尼特(){
};
}
您可以尝试用ngDoCheck()
取代ngOnInit()
。我不确定(实际上我怀疑)这是正确的做法,在任何情况下你都可以尝试
此方法在每个更改检测周期运行(而不是我猜的标准角度算法,这是潜在的问题),因此您应该使MySelectorComponent的category
属性与服务中的更改保持最新
再次需要注意副作用(我不清楚)。您是否尝试过观察物?事实上,我肯定会使用观察物。它给你带来了很多好处,并且已经成为Angular 2应用程序的常见模式。对于Observable,您可以使用ChangeDetectionStaregy.OnPush
,这也可以极大地提高性能。然后,您可以在视图中使用async
管道并直接将可观察对象绑定到那里。如果您需要,如果您不知道如何使用可观察对象,我可以发布一个使用可观察对象的解决方案。但是直接调用服务方法或引用模板中的服务属性并不是一件好事。根据下面的答案,我接受使用主题/行为范式和手动订阅组件是ng2中唯一可行的方法。在“得到”它方面帮了很多忙。看起来仍然像accessi
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() {
};
}