在$scope中丢失此引用$在活动中

Losing this reference in $scope.$on event

本文关键字:引用 活动中 scope      更新时间:2023-09-26

我正在通过设置回调函数从Angularjs注册"$routeChangeSuccessEvent"。当事件被引发时,我无法通过"this"访问我的控制器实例。当前的此实例未定义。

我完整的TypeScript代码:

export class Ctlr {
    static $inject = ["$rootScope","$route"];
    constructor(private $scope: ng.IRootScopeService) {
        this.Scope = $scope;
        this.Title = "";
        //this.Scope.$on("$routeChangeSuccessEvent", this.onRouteChangeStart);
        this.RegisterEvents();
        }
    private RegisterEvents(): void {
        this.Scope.$on("$routeChangeSuccessEvent",(event: ng.IAngularEvent, args: any) => {
        //this is undefined
            console.log(this);
        });
    }
    public Scope: ng.IScope;
    public Title: string;
    public onRouteChangeStart(event: ng.IAngularEvent, args: any) {
        //this is undefined
        this.Title = args.$$route.name);
    }
}

}

我可以使用访问标题属性

 private RegisterEvents(): void {
        var ref = this.Title;
        this.Scope.$on("$routeChangeSuccessEvent",(event: ng.IAngularEvent, args: any) => {
            ref = args.$$route.name;
        });
    }

但这并不是一个真正的解决方案,因为angularJS不会更新其视图。我似乎没有找到合适的参考资料。如果这不可能的话,整个angularjs事件似乎都没有用——这不可能吗?

我也没有发现任何关于这种奇怪行为的话题。这个问题有解决办法吗?

触发回调时作用域会发生变化,这就是this变为未定义的原因。

你的另一个例子:

var ref = this.Title;

实际上只是创建了Title的一个副本,因为它是一个基元类型(字符串)。这就是为什么它也不起作用。更新ref不会更新this.Title

对此,通常的解决方案是开始定义为:

var vm = this;
...
private RegisterEvents(): void {
    this.Scope.$on("$routeChangeSuccessEvent",(event: ng.IAngularEvent, args: any) => {
    //this is undefined
        console.log(vm);
    });
}

因此,与其到处使用this,不如使用vm。请注意,vm可以根据需要进行命名。重要的部分是在this是要在回调中使用的范围中捕获对this的引用。这是因为this而不是基元类型,因为它是一个对象,而不是复制,而是引用。

您的另一个选择是使用bind,您可以将其应用于任何函数,该函数本质上"告诉"JavaScript this将等同于什么。例如

$scope.$on("SomeEventHere", someCallbackFunction.bind(this));

这是您在这里使用的偏好问题,但通常我看到人们使用var something = this;方法。

这是因为它总是引用它的父级,现在它就是函数。所以,如果你愿意,你可以这样做:

private RegisterEvents(): void {
    var ref = this;
    this.Scope.$on("$routeChangeSuccessEvent",(event: ng.IAngularEvent, args: any) => {
        console.log(ref);
    });
}

您可以重新绑定this变量:this.Scope.$on("$routeChangeSuccessEvent",this.onRouteChangeStart.bind(this));

正如其他解决方案中所指出的,并且至少使用TypeScript v1.7,您可以使用胖箭头来使用它,如:

$scope.$on('some-event', () => { console.log('here `this` is not undefined'); });
$scope.$watch('foo.bar', (a,b) => { console.log('here too...'); }
$scope.$on('$routeChangeSuccessEvent', () => { console.log('here too...'); });

但是,如果要传递对同一类函数的引用,则必须使用.bind(this)表示法:

$cope.$on('$routeChangeSuccessEvent', this.onRouteChangeStart.bind(this));