Typescript $inject $timeout into a directive ...在控制器中工作,而不是在 link

Typescript $inject $timeout into a directive ... works in controller, not in link

堆栈: 打字稿 1.7 + Angular 1.49

总结:

我有一个指令。我想要 $inject angular 的 $timeout 服务。它在指令的控制器函数中运行良好,但在 link 函数中运行不正常。我错过了什么?

问题:

MyDirective.ts:

module app.directives {

    export class MyDirective {
        priority = 0;
        restrict = 'E';
        templateUrl = 'template.html';
        scope = {
            'items': '='
        };
        controller = MyController;
        link = MyLink;

        static $inject = ['$timeout'];

        constructor(private  $timeout:ng.ITimeoutService) {
        }
    }

    function MyController($scope:ng.IScope, $timeout:ng.ITimeoutService) {
        console.log("controller", $timeout); // function timeout(fn,delay,invokeApply){ the guts here }
        $timeout(function () {
            console.log("This works fine");
        },3000);
    }

    function MyLink(scope:ng.IScope, element:ng.IAugmentedJQuery, attr:ng.IAttributes, $timeout:ng.ITimeoutService) {
        console.log("link to", $timeout); // MyController {}
        $timeout(function () {
            console.log("This throws the error, TypeError: $timeout is not a function");
        },3000);
    }
}

在directives.ts中连接:

module app.directives {
    angular.module('app').directive('MyDirective',['$timeout',($timeout:ng.ITimeoutService) => new MyDirective($timeout) ]);
}

app.ts

module app {
    angular.module('app', []);
}

什么没用:

最后的笔记

Link函数第4个参数为自己的controller实例

如果你想这样做,你应该这样做:

module app.directives {

    export class MyDirective {
        link = MyLink;

        static $inject = ['$timeout'];

        constructor(public $timeout:ng.ITimeoutService) {
        }
    }

    function MyLink(scope:ng.IScope, element:ng.IAugmentedJQuery, attr:ng.IAttributes, ctrl:any) {
        ctrl.$timeout(function () {
            console.log("This throws the error, TypeError: $timeout is not a function");
        },3000);
    }
}

我知道这并不优雅,但我很难找到更好的解决方案,你觉得怎么样?

Link 函数不直接从指令实例执行,因此您不会将 this 作为指令的配置实例(您通过 new 运算符实例化)。此外,与控制器构造函数不同,您不能向 link 函数(即指令构造函数的用途)注入任何内容,link 函数的参数由指令执行逻辑自动传入。您可以使用箭头运算符来解决此问题。

示例:

 export class MyDirective {
    priority = 0;
    restrict = 'E';
    templateUrl = 'template.html';
    scope = {
        'items': '='
    };
    controller = MyController;

    link:ng.IDirectiveLinkFn = (scope:ng.IScope, element:ng.IAugmentedJQuery, attr:ng.IAttributes) => {

      //Here
      this.$timeout(function () {

      },3000);
    };

    constructor(private  $timeout:ng.ITimeoutService) {
    }
}

或者您可以使用 function.bind 绑定上下文。即 link = MyLink; 并使用 this.$timeout.

访问 $timeout

如果感兴趣,您可以看看通过使用指令的实验性装饰器来创建一些语法糖,或者您可以尝试探索一些东西 like this。但是(只是我的意见)使用 class 作为指令配置似乎有点矫枉过正,你还不如使用带有静态注入的函数。