AngularJS TypeScript 指令链接函数

Posted

技术标签:

【中文标题】AngularJS TypeScript 指令链接函数【英文标题】:AngularJS TypeScript directive link function 【发布时间】:2014-07-05 20:15:14 【问题描述】:

我正在尝试使用 TypeScript 创建一个 AngularJS 指令。我的指令需要“ngModel”,并且我还使用了在我的指令中注入的自定义服务。 我的主要问题是我的服务不能在我的链接函数中使用。

这是我想要实现的一个示例:

module app.directives 

    export var directiveName: string = "theDirective";

    angular.module("myApp").directive(directiveName, 
           (myFactory: app.services.MyFactory) =>
           
                return new MyDirective(myFactory);
           );

    export interface IMyDirectiveScope extends ng.IScope 
        ngModel: ng.INgModelController;
    

    export class MyDirective implements ng.IDirective 

        restrict = "A";
        require = "ngModel";
        scope = 
            ngModel:'='
        

        constructor(private myFactory: app.services.MyFactory) 

        


        link(scope: IMyDirectiveScope , elem: JQuery, attributes: ng.IAttributes, ngModel: ng.INgModelController) 
            //this is window here

            elem.bind('blur', (evt: JQueryEventObject) =>   
                 //keyword this is also window here, so yeah bummer indeed
                 validate(); 
            );

            function validate() 
                 //I need to use my factory here, but I can seem to get it.
                 //this is always window and I'm kinda stuck here
            
        
    

我似乎找不到关于这个主题的更高级的东西。我发现的所有示例似乎都没有使用服务或复杂的链接功能。 请用某种例子回答这个问题。你认为这很诡计。

更新: 我的链接函数中的“this”是窗口而不是“MyDirective”这一事实对我来说没有多大意义。任何想法为什么会这样?

【问题讨论】:

【参考方案1】:

使用类并从 ng.IDirective 继承是 TypeScript 的方式。

TypeScript 支持 EcmaScript 6 中的粗箭头函数 () =>。 这是一种简写语法,也改变了 this 关键字的工作方式:

class MyDirective implements ng.IDirective 
    restrict = 'A';
    require = 'ngModel';
    scope = 
        ngModel: '='
    

    constructor(private myFactory: app.services.MyFactory) 
    

    link = (scope: IMyDirectiveScope, elem: JQuery, attributes: ng.IAttributes, ngModel: ng.INgModelController) => 
        console.log(this); // this points to MyDirective instance instead of Window

        elem.bind('blur', (evt: JQueryEventObject) => 
            console.log(this); // this points to MyDirective instance instead of Window
            this.validate(); 
        );
    

    validate() 
        console.log(this); // this points to MyDirective instance instead of Window
    


    static factory(): ng.IDirectiveFactory 
        var directive = (myFactory: app.services.MyFactory) => new MyDirective(myFactory);
        directive.$inject = ['myFactory'];
        return directive;
    


app.directive('mydirective', MyDirective.factory());

你也可以依赖老式的var self = this;模式:

class MyDirective implements ng.IDirective 
    restrict = 'A';
    require = 'ngModel';
    scope = 
        ngModel: '='
    

    constructor(private myFactory: app.services.MyFactory) 
    

    link = (scope: IMyDirectiveScope, elem: JQuery, attributes: ng.IAttributes, ngModel: ng.INgModelController) => 
        console.log(this); // this points to MyDirective instance instead of Window

        var self = this;

        function validate() 
            console.log(self); // self points to MyDirective instance
        

        elem.bind('blur', function(evt: JQueryEventObject) 
            console.log(self); // self points to MyDirective instance
            validate(); 
        );
    

相关回答:https://***.com/a/29223535/990356

【讨论】:

这个 IMyDirectiveScope 类型在哪里定义?而对于 app.services.MyFactory 它的定义是什么? @Oscar 你应该先阅读这个问题:interface IMyDirectiveScope extends ng.IScope 我们可以在不使用链接功能的情况下实现这一点吗?我正在使用 Angular 1.4,由于我们将代码转换为 Angular 2.0 并且那里不支持链接函数,所以我不想使用链接函数编写此逻辑。所以请告诉我是否可以在没有的情况下访问该元素链接函数。 这实际上并不完全有效。您是否尝试过在一个父控制器下添加两个相同的指令?查看变量的作用域,您会注意到两个指令的作用域都是最后一个指令隔离作用域,行为不正确。【参考方案2】:

类非常适合控制器和指令控制器,但我不认为我会为整个指令使用一个。但如果你愿意,你可能不得不做这样的事情:

export class MyDirective implements ng.IDirective 

    public link;

    restrict = "A";
    require = "ngModel";
    scope = 
        ngModel:'='
    

    constructor(private myFactory: app.services.MyFactory) 
        this.link = this.unboundLink.bind(this);
    


    unboundLink(scope: IMyDirectiveScope , elem: JQuery, attributes: ng.IAttributes, ngModel: ng.INgModelController) 
        //Now you should be able to access myFactory
        this.myFactory.doSomething();

        elem.bind('blur', (evt: JQueryEventObject) =>   
             //keyword this is also window here, so yeah bummer indeed
             validate(); 
        );

        function validate() 
             //I need to use my factory here, but I can seem to get it.
             //this is always window and I'm kinda stuck here
        
    

编辑:没有类你可以做这样的事情:

angular.module("myApp").directive("theDirective", 
    function(myFactory: app.services.MyFactory) 
        return 
            restrict: 'A',
            require: 'ngModel',
            scope: 'ngModel': '=',
            link: function(scope: IMyDirectiveScope , elem: JQuery, attributes: ng.IAttributes, ngModel: ng.INgModelController) 
                //You can access myFactory like this.
                myFactory.doSomething();
            
        
    
);

【讨论】:

谢谢这个作品,你能给我一个例子,你将如何在没有课程的情况下处理这种情况? @user1613512 我编辑了我的答案以包含一个没有类的示例 写 unboundLink(...) var self = this; ... 然后你可以在 validate() 中使用 self 变量而不是 this。

以上是关于AngularJS TypeScript 指令链接函数的主要内容,如果未能解决你的问题,请参考以下文章

带有 ControllerAs 和 TypeScript 类的 AngularJs 指令

如何使用 TypeScript 解决 AngularJS 指令

Angularjs+Typescript 指令实现 $compile

在 Typescript 中将 angularjs 指令实现为类

AngularJS 和 Typescript:如何将类/类型分配为指令的控制器?

在 AngularJS 上使用 Typescript 的指令中控制器的范围