“此"在使用TypeScript构建的Angular指令的侧链接函数中未定义 [英] "this" undefined in side link function in Angular directive built with TypeScript

查看:71
本文介绍了“此"在使用TypeScript构建的Angular指令的侧链接函数中未定义的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是TypeScript和Angular的相对新手,所以我在这里可能犯了一些非常基本的错误.

我正在尝试创建一个抽象基类,可以从该基类派生多个指令,每个指令都将实现一个自定义验证规则.我的代码可以编译,但是可以在运行时失败,特别是在尝试调用this.isValid(...)时,因为此时"this"是未定义的.谁能看到这段代码有什么问题吗?

module App.Common.Directives {
    'use strict';

    export abstract class ValidatorBase implements angular.IDirective {

        require = 'ng-model';
        restrict = 'A';

        constructor(private validationErrorKey: string) { }

        link(scope: angular.IScope, el: angular.IAugmentedJQuery, attributes: Directives.IValidatorAttributes, controller: angular.IFormController) {
            //tsc writes "var _this = this;" here, but this is undefined
            scope.$watch(attributes.ngModel, () => {
                const val: string = el.val();
                const valid = this.isValid(val, el, scope, attributes, controller);
                controller.$setValidity(this.validationErrorKey, valid, undefined);
            });
        }

        abstract isValid(val: any, el?: angular.IAugmentedJQuery, scope?: angular.IScope, attributes?: Directives.IValidatorAttributes, controller?: angular.IFormController): boolean;

    }
}

这是来自TypeScript编译器的此类的输出:

var App;
(function (App) {
    var Common;
    (function (Common) {
        var Directives;
        (function (Directives) {
            'use strict';
            var ValidatorBase = (function () {
                function ValidatorBase(validationErrorKey) {
                    this.validationErrorKey = validationErrorKey;
                    this.require = 'ng-model';
                    this.restrict = 'A';
                }
                ValidatorBase.prototype.link = function (scope, el, attributes, controller) {
                    var _this = this; //this is undefined when we get here
                    scope.$watch(attributes.ngModel, function () {
                        var val = el.val();
                        var valid = _this.isValid(val, el, scope, attributes, controller);
                        controller.$setValidity(_this.validationErrorKey, valid, undefined);
                    });
                };
                return ValidatorBase;
            })();
            Directives.ValidatorBase = ValidatorBase;
        })(Directives = Common.Directives || (Common.Directives = {}));
    })(Common = App.Common || (App.Common = {}));
})(App || (App = {}));

解决方案

在Angular指令中,将this视为类实例是不安全的,因为函数可以具有自己的词法this,并且它们实际上具有它. >

thiscontroller中的控制器实例(使用"controller as"语法,它可能会或可能不会在作用域中公开).

thiscompile中的DDO对象(因此this在上下文中是上下文).

在链接功能中,

thisundefined(在严格模式下).

如果不确定词法this或要覆盖它,请使用箭头功能:

link = (...) => { ... };

I'm a relative newbie to both TypeScript and Angular so I'm probably doing something very basic wrong here.

I'm trying to create an abstract base class from which I can derive multiple directives, each of which will implement a single custom validation rule. My code compiles okay, but fails at runtime, specifically when it tries to call this.isValid(...) because "this" is undefined at that point. Can anyone see what is wrong with this code?

module App.Common.Directives {
    'use strict';

    export abstract class ValidatorBase implements angular.IDirective {

        require = 'ng-model';
        restrict = 'A';

        constructor(private validationErrorKey: string) { }

        link(scope: angular.IScope, el: angular.IAugmentedJQuery, attributes: Directives.IValidatorAttributes, controller: angular.IFormController) {
            //tsc writes "var _this = this;" here, but this is undefined
            scope.$watch(attributes.ngModel, () => {
                const val: string = el.val();
                const valid = this.isValid(val, el, scope, attributes, controller);
                controller.$setValidity(this.validationErrorKey, valid, undefined);
            });
        }

        abstract isValid(val: any, el?: angular.IAugmentedJQuery, scope?: angular.IScope, attributes?: Directives.IValidatorAttributes, controller?: angular.IFormController): boolean;

    }
}

Here is the output from the TypeScript compiler for this class:

var App;
(function (App) {
    var Common;
    (function (Common) {
        var Directives;
        (function (Directives) {
            'use strict';
            var ValidatorBase = (function () {
                function ValidatorBase(validationErrorKey) {
                    this.validationErrorKey = validationErrorKey;
                    this.require = 'ng-model';
                    this.restrict = 'A';
                }
                ValidatorBase.prototype.link = function (scope, el, attributes, controller) {
                    var _this = this; //this is undefined when we get here
                    scope.$watch(attributes.ngModel, function () {
                        var val = el.val();
                        var valid = _this.isValid(val, el, scope, attributes, controller);
                        controller.$setValidity(_this.validationErrorKey, valid, undefined);
                    });
                };
                return ValidatorBase;
            })();
            Directives.ValidatorBase = ValidatorBase;
        })(Directives = Common.Directives || (Common.Directives = {}));
    })(Common = App.Common || (App.Common = {}));
})(App || (App = {}));

解决方案

In Angular directives it is unsafe to consider this a class instance because functions can have their own lexical this, and they actually have it.

this is controller instance in controller (which may or may not be exposed on scope with 'controller as' syntax).

this is DDO object in compile (so this is contextual here).

this is undefined in linking functions (in strict mode).

Use arrow functions if you're unsure about lexical this or want to override it:

link = (...) => { ... };

这篇关于“此"在使用TypeScript构建的Angular指令的侧链接函数中未定义的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆