使用TypeScript和$ inject机制定义AngularJS指令

Mil*_*kov 45 directive inject angularjs typescript

最近我开始重构我正在使用TypeScript进行的一个Angular项目.使用TypeScript类来定义控制器非常方便,并且由于static $inject Array<string>属性而适用于缩小的JavaScript文件.并且您可以获得非常干净的代码,而无需从类定义中拆分Angular依赖项:

 module app {
  'use strict';
  export class AppCtrl {
    static $inject: Array < string > = ['$scope'];
    constructor(private $scope) {
      ...
    }
  }

  angular.module('myApp', [])
    .controller('AppCtrl', AppCtrl);
}
Run Code Online (Sandbox Code Playgroud)

现在我正在寻找解决方案来处理指令定义的类似情况.我找到了一个很好的做法,将指令定义为函数:

module directives {

  export function myDirective(toaster): ng.IDirective {
    return {
      restrict: 'A',
      require: ['ngModel'],
      templateUrl: 'myDirective.html',
      replace: true,
      link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrls) => 
        //use of $location service
        ...
      }
    };
  }


  angular.module('directives', [])
    .directive('myDirective', ['toaster', myDirective]);
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我被迫在指令定义中定义Angular依赖项,如果定义和TypeScript类在不同的文件中,则可能非常容易出错.使用typescript和$inject机制定义指令的最佳方法是什么,我正在寻找一种实现TypeScript IDirectiveFactory接口的好方法,但我对我找到的解决方案并不满意.

tan*_*y_k 110

使用类和继承自ng.IDirective是使用TypeScript的方法:

class MyDirective implements ng.IDirective {
    restrict = 'A';
    require = 'ngModel';
    templateUrl = 'myDirective.html';
    replace = true;

    constructor(private $location: ng.ILocationService, private toaster: ToasterService) {
    }

    link = (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrl: any) => {
        console.log(this.$location);
        console.log(this.toaster);
    }

    static factory(): ng.IDirectiveFactory {
        const directive = ($location: ng.ILocationService, toaster: ToasterService) => new MyDirective($location, toaster);
        directive.$inject = ['$location', 'toaster'];
        return directive;
    }
}

app.directive('mydirective', MyDirective.factory());
Run Code Online (Sandbox Code Playgroud)

相关回答:https://stackoverflow.com/a/29223360/990356

  • 优秀作品!到目前为止,我见过最干净的方法! (3认同)
  • 我们可以在不使用链接功能的情况下实现此目的吗 我正在使用Angular 1.4,因为我们将代码转换为Angular 2.0并且不支持链接函数,我不想使用链接函数编写这个逻辑.所以如果有可能访问元素,请告诉我链接功能. (2认同)

Mob*_*ent 33

我更喜欢controller为指令指定一个并且只在那里注入依赖项.

在控制器及其接口到位的情况下,我强烈地将链接功能的第4个参数输入到控制器的界面,并享受从那里开始使用它.

将依赖关系从链接部分转移到指令的控制器允许我从控制器的TypeScript中受益,同时我可以保持我的指令定义功能简短(与指令类方法不同,它需要为指令指定和实现静态工厂方法) ):

module app {
"use strict";

interface IMyDirectiveController {
    // specify exposed controller methods and properties here
    getUrl(): string;
}

class MyDirectiveController implements IMyDirectiveController {

    static $inject = ['$location', 'toaster'];
    constructor(private $location: ng.ILocationService, private toaster: ToasterService) {
        // $location and toaster are now properties of the controller
    }

    getUrl(): string {
        return this.$location.url(); // utilize $location to retrieve the URL
    }
}

function myDirective(): ng.IDirective {
    return {
        restrict: 'A',
        require: 'ngModel',
        templateUrl: 'myDirective.html',
        replace: true,

        controller: MyDirectiveController,
        controllerAs: 'vm',

        link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attributes: ng.IAttributes, controller: IMyDirectiveController): void => {
            let url = controller.getUrl();
            element.text('Current URL: ' + url);
        }
    };
}

angular.module('myApp').
    directive('myDirective', myDirective);
}
Run Code Online (Sandbox Code Playgroud)

  • 恕我直言这是最好的答案,这也是我将如何做到这一点,因为这不需要任何特殊处理,没有变通办法等.只是简单的默认控制器注入. (5认同)

bas*_*rat 9

在这种情况下,我被迫在指令定义中定义角度依赖项,如果定义和typescript类在不同的文件中,这可能非常容易出错

解:

 export function myDirective(toaster): ng.IDirective {
    return {
      restrict: 'A',
      require: ['ngModel'],
      templateUrl: 'myDirective.html',
      replace: true,
      link: (scope: ng.IScope, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, ctrls) => 
        //use of $location service
        ...
      }
    };
  }
  myDirective.$inject = ['toaster']; // THIS LINE
Run Code Online (Sandbox Code Playgroud)