Javascript 当注入服务上的值更新时,如何更新AngularJS(使用TypeScript)控制器中的值
目前,我正试图从Actionscript的背景中学习Typescript和AngularJS。我一直在玩一些代码实验,van通常实现了我想要的,但并不总是以我想要的方式 目前我有以下代码:Javascript 当注入服务上的值更新时,如何更新AngularJS(使用TypeScript)控制器中的值,javascript,angularjs,typescript,Javascript,Angularjs,Typescript,目前,我正试图从Actionscript的背景中学习Typescript和AngularJS。我一直在玩一些代码实验,van通常实现了我想要的,但并不总是以我想要的方式 目前我有以下代码: export class CountingService { countScope = { count : 0 }; public increment() { this.countScope.count++; } } export class PageCon
export class CountingService
{
countScope = { count : 0 };
public increment()
{
this.countScope.count++;
}
}
export class PageController
{
constructor( private service : CountingService )
{
this.countScope = service.countScope;
}
public localCount : number = 0;
countScope;
public increment()
{
this.service.increment();
this.localCount++;
}
}
我有一些不同的观点,其中包含了这段代码:
<div ng-controller="PageController as page">
<Button ng-click="page.increment()">Count {{page.localCount}}/{{page.countScope.count}}</Button>
</div>
计数{{page.localCount}}/{{page.countScope.Count}
当我在视图之间切换时,localCount总是重置为零,但服务的countScope中的计数不会重置,而是由每个不同的控制器递增
这是可行的,但有点乱。我必须让非类型化的localScope四处浮动,视图需要了解countScope对象的内部结构,并绑定到page.countScope.count,而不是像page.globalCount这样的内容
在Actionscript中,我将在控制器上设置只读。每次值更改时,服务都会调度一个事件,控制器将侦听该事件,然后更新它自己的属性,然后更新视图
我的问题是,实现我在这里所做的事情的最佳实践方式是什么,它不需要视图了解非类型化对象的内部。
我很确定公共获取者不存在,但我可以发送并监听事件吗
非常感谢简短回答:服务是单例的,即构造函数只调用一次。如果您想重置它,您可以从控制器的构造函数中执行此操作
this.service.countScope.count=0
笔记
我看到了很多我不喜欢的代码示例。但我相信这只是一个样本,所以不要把它当作个人冒犯;)
- 没有名为
的服务。称之为service
countService
- 服务上没有成员
。只需使用countScope
。并且不要将计数
复制到当前控制器。只需使用countScope
this.countService.count
由于您将控制器设置为
page
和page.service
是一种简单的{{page.service.countScope.count}}
将显示计数。这是答案1,我想这就是John Kurlak所说的方法:
export class CountingService
{
serviceCount : number = 100;
public increment()
{
this.serviceCount++;
}
}
export class PageController
{
constructor( $scope, private service : CountingService )
{
this.serviceCount = service.serviceCount;
$scope.$watch( () => this.service.serviceCount, ( newValue : number, oldValue : number ) => this.updateLocal( newValue, oldValue ) );
}
localCount : number = 0;
serviceCount : number;
public increment()
{
this.service.increment();
this.localCount++;
}
private updateLocal( newValue : number, oldValue : number )
{
this.serviceCount = newValue;
}
}
这是可行的,我想这就是我想要的解决方案。不过,我也有一些不喜欢的地方
我不喜欢将$scope注入到我的服务中。这似乎是对我不需要的东西的额外依赖。
我也真的不喜欢那些可以通过任何方式更新并破坏封装的公共成员。我想用getter解决这个问题,但我不知道如何更新到ECMAScript 5(这里的问题:)
约翰-这就是你的提议吗?如果有人对这个答案提出赞成和反对的意见,我将非常感激。
我将把这个标记为答案,因为我认为这是我开始时想要的答案。这是答案2,我认为这是PSL想要的(或类似的东西)
接口计数回调
{
家长:任何;
回调:(值:number)=>void;
}
导出类计数服务
{
private _observer回调:Array=[];
私有服务计数:数字=100;
公共增量()
{
这个;
这个。notifyObservators();
}
公共注册表ObserverCallback(callbackParent:any,callbackFunction:(值:number)=>void)
{
var callback:CountingCallBack={parent:callbackParent,callback:callbackFunction};
this.\u observer callbacks.push(callback);
this.updateObserver(回调);
}
私人观察员()
{
forEach(this.\u observer回调,this.updateObserver,this);
}
私有更新观察服务器(回调:CountingCallBack)
{
callback.callback.apply(callback.parent,[this.\u serviceCount]);
}
}
导出类页面控制器
{
构造函数(专用计数服务:计数服务)
{
countingService.registerObserverCallback(this,this.updateLocal);
}
localCount:number=0;
serviceCount:编号;
公共增量()
{
this.countingService.increment();
这是.localCount++;
}
私有updateLocal(newValue:number)
{
this.serviceCount=newValue;
}
}
我很高兴能够实现这一点,因为我现在了解了函数接口语法的工作原理(我非常喜欢它),并且我成功地解决了控制器上updateLocal函数中的“this”范围问题
这个解决方案不需要注入$scope,这很好,但我发现回调实现相当混乱。我不喜欢将控制器和控制器上的函数传递给服务来添加回调。
我想我可以创建一个接口,ICountListener或其他什么,然后将其传递给服务,然后在控制器上调用updateCount。那样会更整洁一些,但还是不太好。
有没有比这更简洁的方法来设置回调
这段代码的最大问题(也是不应该使用它的原因)是它造成了内存泄漏。如果继续切换视图,控制器将永远不会被清理,因此内存中还有许多控制器,所有控制器都会响应更新的计数。
清理回调和取消注册回调相对容易,但这可能涉及注入$scope,然后监听销毁事件(我不知道怎么做,但我认为这在上面的评论中已经讨论过了)。最后回答三个问题。我做的
interface CountingCallBack
{
parent : any;
callback : ( value : number ) => void;
}
export class CountingService
{
private _observerCallBacks : Array<CountingCallBack> = [];
private _serviceCount : number = 100;
public increment()
{
this._serviceCount++;
this.notifyObservers();
}
public registerObserverCallback( callbackParent : any, callbackFunction : ( value : number ) => void )
{
var callback : CountingCallBack = { parent : callbackParent, callback : callbackFunction };
this._observerCallBacks.push( callback );
this.updateObserver( callback );
}
private notifyObservers()
{
angular.forEach( this._observerCallBacks, this.updateObserver, this );
}
private updateObserver( callback : CountingCallBack )
{
callback.callback.apply( callback.parent, [ this._serviceCount ] );
}
}
export class PageController
{
constructor( private countingService : CountingService )
{
countingService.registerObserverCallback( this, this.updateLocal );
}
localCount : number = 0;
serviceCount : number;
public increment()
{
this.countingService.increment();
this.localCount++;
}
private updateLocal( newValue : number )
{
this.serviceCount = newValue;
}
}
export class CountingService
{
private _serviceCount : number = 100;
public increment()
{
this._serviceCount++;
}
get serviceCount() : number
{
return this._serviceCount;
}
}
export class PageController
{
constructor( private countingService : CountingService )
{}
private _localCount : number = 0;
get localCount() : number
{
return this._localCount;
}
get serviceCount() : number
{
return this.countingService.serviceCount;
}
public increment()
{
this.countingService.increment();
this._localCount++;
}
}
export class CountingService {
//Create a stream of changes. When caller subscribe always give them the most recent value.
private rawCountStream = new Rx.Subject<number>();
public countStream : Rx.Observable<number>;
private count = 0;
constructor() {
this.countStream = this.rawCountStream.replay(1);
}
public increment() {
this.count++;
//Pump the value to callers.
this.rawCountStream.onNext(this.count);
}
}
export class PageController {
constructor(private service: CountingService) {
//Listen to the stream of changes.
service.countStream.subscribe(value => {
//do something
//IMPORTANT If you want angular to update the ui you will need to call $apply on a scope.
//RXJS has a scheduler for this so you look at that here.
//https://github.com/Reactive-Extensions/rx.angular.js
}
);
}
public localCount: number = 0;
public increment() {
this.service.increment();
this.localCount++;
}
}