如何使用 TypeScript 解决 AngularJS 指令

Posted

技术标签:

【中文标题】如何使用 TypeScript 解决 AngularJS 指令【英文标题】:How to work around AngularJS Directive with TypeScript 【发布时间】:2016-08-30 22:11:11 【问题描述】:

我有以下脚本,dateTimePicker 作为 AngularJS 指令:

(function () 
    'use strict';

    var module = angular.module('feedApp');

    module.directive('datetimepicker', [
        '$timeout',
        function ($timeout) 
            return 
                require: '?ngModel',
                restrict: 'EA',
                scope: 
                    options: '@',
                    onChange: '&',
                    onClick: '&'
                ,
                link: function ($scope, $element, $attrs, controller) 
                    $($element).on('dp.change', function () 
                        $timeout(function () 
                            var dtp = $($element).data('DateTimePicker');
                            controller.$setViewValue(dtp.date().format('MM/DD/YYYY HH:mm'));
                            $scope.onChange();
                        );
                    );

                    $($element).on('click', function () 
                        $scope.onClick();
                    );

                    controller.$render = function () 
                        if (!!controller) 
                            if (controller.$viewValue === undefined) 
                                controller.$viewValue = null;
                            
                            else if (!(controller.$viewValue instanceof moment)) 
                                controller.$viewValue = moment(controller.$viewValue);
                            
                            $($element).data('DateTimePicker').date(controller.$viewValue);
                        
                    ;

                    $($element).datetimepicker($scope.$eval($attrs.options));
                
            ;
        
    ]);
)();

我想用 TypeScript 重写它。这是我现在拥有的代码:

namespace feedApp 
    'use strict';

    DateTimePicker.$inject = ['$timeout'];

    function DateTimePicker($timeout: ng.ITimeoutService): ng.IDirective 
        var directive = <ng.IDirective>
            require: '?ngModel',
            restrict: 'EA',
            scope: 
                options: '@',
                onChange: '&',
                onClick: '&'
            ,
            link: link
        ;

        function link(scope: ng.IScope, element: JQuery, attrs: ng.IAttributes, controller: ng.INgModelController): void 
            $(element).on('dp.change', function () 
                $timeout(function () 
                    var dtp = $(element).data('DateTimePicker');
                    controller.$setViewValue(dtp.date().format('MM/DD/YYYY HH:mm'));
                    scope.onChange();
                );
            );

            $(element).on('click', function () 
                scope.onClick();
            );

            controller.$render = function () 
                if (!!controller) 
                    if (controller.$viewValue === undefined) 
                        controller.$viewValue = null;
                    
                    else if (!(controller.$viewValue instanceof moment)) 
                        controller.$viewValue = moment(controller.$viewValue);
                    
                    $(element).data('DateTimePicker').date(controller.$viewValue);
                
            ;

            $(element).datetimepicker(scope.$eval(attrs.options));
        

        return directive;


angular.module("feedApp")
    .directive("datetimepicker", DateTimePicker);

我没有使用 TypeScript 的经验,我真的不知道使用 TS 更改像 $(element).on 这样的 jQuery 元素的最佳做法是什么。如何使用

    scope: 
        options: '@',
        onChange: '&',
        onClick: '&'
    ,

在 TypeScript link 函数中?提前感谢您的帮助。

【问题讨论】:

在您的指令中使用 jQuery 处理诸如“点击”之类的事情的基本原理是什么?我也从未见过像 $($element) 这样的东西,那背后的想法是什么?我只是好奇。没有冒犯:) $($element) 是完全多余的:角度元素已经被包裹在 jqLit​​e 中(或者如果你已经加载了 jquery)所以所有使用 $($element) 的东西都可以更简单地写成 $element。跨度> 第一个用JS写的例子是从网上摘来的,可以用。 $($element)(如果我理解得足够好的话)只是指向 html 元素,因此您可以使用 .on 等事件。 @Duncan 这对我不起作用,但我没有 jqLit​​e。是否也需要在 TypeScript 中使用它?感谢您的建议 jqlite 作为 Angular 的一部分包含在内,它在 angular.element 中包含的任何内容上提供 jQuery 的子集,其中包括传递给指令的 $element,除非您专门加载 jquery,否则将使用它。如果您先加载 angular 然后加载 jquery,它可能不起作用,因为当您需要 jquery 时,angular 会包装在 jqlite 中。 Typescript 不会影响你是否需要使用 jquery。 【参考方案1】:

使用 bindToController 访问指令控制器内的范围变量。 为了更好的结构/理解,请在不同的文件中声明指令的不同组件,例如控制器应该在一个唯一的文件中,html 应该有自己的文件等。

请参阅Directive testing 问题和typescript github sample project 了解更多信息。

如果您需要更多说明,请告诉我。

问候

阿杰

【讨论】:

很好的例子! :) 谢谢你的回答。在互联网上很难找到关于 angular + ts 的有价值的东西。这对我帮助很大:) @Marox 请参考medium.com/@bojzi/… 以获得更多帮助。同一 github 存储库的博客。谢谢。:-)

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

在 typescript / angular2 环境和后端的 nodejs 中设置持久会话时遇到问题

从Angular TypeScript中来自firestore的数据中获取未定义

如何使用 TypeScript 解决 AngularJS 指令

升级到 Ionic 5 后,TypeScript 编译中缺少 src/zone-flags.ts

如何解决 Typescript 中有关 `withStateHandlers` 的错误

如何解决 rxjs Typescript 错误(Ionic 3,angularfire2)