Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angularjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用ES6类作为Angular 1.x指令_Javascript_Angularjs_Class_Angularjs Directive_Ecmascript 6 - Fatal编程技术网

Javascript 使用ES6类作为Angular 1.x指令

Javascript 使用ES6类作为Angular 1.x指令,javascript,angularjs,class,angularjs-directive,ecmascript-6,Javascript,Angularjs,Class,Angularjs Directive,Ecmascript 6,我正在做一个小项目来研究ES6带来的好东西,我试图将register类设置为angular指令,但我遇到了一个错误“TypeError:无法将类作为函数调用”,但从示例中我发现他们只是编写类并将其注册为angular指令。这是我的指令 class dateBlock { constructor () { this.template = '/app/dateblock/dateblock.html'; this.restrict = 'AE'; this.scope =

我正在做一个小项目来研究ES6带来的好东西,我试图将register类设置为angular指令,但我遇到了一个错误“TypeError:无法将类作为函数调用”,但从示例中我发现他们只是编写类并将其注册为angular指令。这是我的指令

class dateBlock {
  constructor () {
    this.template = '/app/dateblock/dateblock.html';
    this.restrict = 'AE';
    this.scope = {};
  }
};

export default dateBlock
以及我的索引,我在其中导入它,然后声明它

import calendarController from './calendar/calendar.js'
import dateBlock from './dateblock/dateblock.js'

function setup($stateProvider) {
    $stateProvider
      .state('base', {
        url: '',
        controller: calendarController,
        templateUrl: '/app/calendar/calendar.html'
      });
    };

setup.$inject = ['$stateProvider']

var app = angular.module('calApp',['ngAnimate','ui.router','hmTouchEvents', 'templates'])
  .config(setup)
  .controller('calendarController', calendarController)
  .directive('dateBlock', dateBlock)

如果我错过了关键的一步,我很想听到。另外一个附带问题是,将所有应用程序组件导入索引并在那里注册,还是导出应用程序并在组件中导入并注册?我遇到了类似的问题。但在我的例子中,当我部署到生产环境时,它成功了,但失败了。但它失败了,因为生产中使用了最新版本的6to5。 这可以通过使用
npm shrinkwrap
来防止。
根据最新的ES6规范,您不能使用这样的类

如注释中所述,
module.directive()
方法需要工厂函数而不是构造函数

最简单的方法是将类包装在返回实例的函数中:

angular.module('app')
    .directive('dateBlock', () => new DateBlock());
但是,这只在最有限的意义上起作用-它不允许依赖项注入,并且指令的
编译
链接
功能(如果已定义)将无法按预期工作

事实上,这是一个我已经深入研究过的问题,结果证明解决起来相当棘手(至少对我来说)

我写了一篇内容广泛的文章,介绍了我的解决方案,但就您而言,我可以向您指出需要解决的两个主要问题:

  • 我认为,完整的解决方案需要太多的代码才能粘贴到这里,但我已经准备了一个工作演示项目,它允许您将指令定义为ES6类,如下所示:

    class MyDirective {
        /*@ngInject*/
        constructor($interval) {
            this.template = '<div>I\'m a directive!</div>';
            this.restrict = 'E';
            this.scope = {}
            // etc. for the usual config options
    
            // allows us to use the injected dependencies
            // elsewhere in the directive (e.g. compile or link function)
            this.$interval = $interval;
        }
    
        // optional compile function
        compile(tElement) {
            tElement.css('position', 'absolute');
        }
    
        // optional link function
        link(scope, element) {
            this.$interval(() => this.move(element), 1000);
        }
    
        move(element) {
            element.css('left', (Math.random() * 500) + 'px');
            element.css('top', (Math.random() * 500) + 'px');
        }
    }
    
    // `register` is a helper method that hides all the complex magic that is needed to make this work.
    register('app').directive('myDirective', MyDirective);
    
    class-MyDirective{
    /*@Nginect*/
    构造函数($interval){
    this.template='I'm a directive!';
    this.restrict='E';
    this.scope={}
    //等,以获取常用的配置选项
    //允许我们使用注入的依赖项
    //指令中的其他地方(例如编译或链接函数)
    这个.$interval=$interval;
    }
    //可选编译函数
    编辑(远程通讯){
    css(‘位置’、‘绝对’);
    }
    //可选链接功能
    链接(范围、元素){
    this.$interval(()=>this.move(元素),1000);
    }
    移动(元素){
    css('left',(Math.random()*500)+'px');
    css('top',(Math.random()*500)+'px');
    }
    }
    //register是一个helper方法,它隐藏了实现此功能所需的所有复杂魔法。
    寄存器('app')。指令('myDirective',myDirective);
    

    检查一下,迈克尔的钱就在上面:

    directive()方法需要一个工厂函数

    然而我用另一种技术解决了它,我想稍微干净一点,它对我来说很好,但并不完美。。。 我定义了一个静态方法,该方法返回模块()所期望的工厂

    在我的应用程序中,我会:

    angular.module('vineyard',[]).directive('vineScroller', VineDirective.directiveFactory)
    

    我相信没有其他方法可以使用类+指令,在这一点上,只需选择简单的一种;-)

    我也面临同样的问题。我第一次尝试通过ES6类解决这个问题,但我的依赖项有问题。在我意识到有两种编写代码的风格之后,我尝试了。总之,我使用了样式,并在我的rails应用程序ES6中获得了以下works代码:

    ((angular) => {
     'use strict';
    
      var Flash = ($timeout) => {
       return {
         restrict: 'E',
         scope: {
           messages: '=messages'
         },
         template: (() => {
           return "<div class='alert flash-{{ message[0] }}' ng-repeat = 'message in messages'>" +
                    "<div class= 'close' ng-click = 'closeMessage($index)' data-dismiss = 'alert' > × </div>" +
                    "<span class= 'message' >{{ message[1] }}</ span>" +
                  "</ div>";
         }),
         link: (scope) => {
           scope.closeMessage = (index) => {
             scope.messages.splice(index, 1)
           };
    
          $timeout(() => {
            scope.messages = []
          }, 5000);
        }
      }
    };
    
    Flash.$inject = ['$timeout'];
    
    angular.module('Application').directive('ngFlash', Flash);
    
    })(window.angular);
    
    ((角度)=>{
    "严格使用",;
    var Flash=($timeout)=>{
    返回{
    限制:'E',
    范围:{
    消息:'=消息'
    },
    模板:(()=>{
    返回“”+
    " × " +
    “{{消息[1]}”+
    "";
    }),
    链接:(范围)=>{
    scope.closeMessage=(索引)=>{
    作用域消息拼接(索引,1)
    };
    $timeout(()=>{
    scope.messages=[]
    }, 5000);
    }
    }
    };
    Flash.$inject=['$timeout'];
    角度。模块(“应用”)。指令(“ngFlash”,Flash);
    })(窗口角度);
    
    我知道我可以用ES6风格的函数和变量做一些改进。
    我希望有帮助

    在我看来,没有必要使用register.js这样的外部库,因为您可以通过以下方式将指令创建为ES6类:

    class MessagesDirective {
        constructor() {
            this.restrict = 'E'
            this.templateUrl = 'messages.html'
            this.scope = {}
        }
    
        controller($scope, $state, MessagesService) {
            $scope.state = $state;
            $scope.service = MessagesService;
        }
    
        link(scope, element, attrs) {
            console.log('state', scope.state)
            console.log('service', scope.service)
        }
    }
    angular.module('messages').directive('messagesWidget', () => new MessagesDirective)
    

    使用指令控制器允许您插入依赖项,即使没有其他声明(例如,
    MessagesDirective.$inject=['$scope'、'$state'、'MessagesService']
    ),所以如果需要,您可以通过作用域在链接函数中使用服务

    一个更简单、更干净、更易读的解决方案在我的项目中,我使用了一种语法sugar进行注射。ES6使指令使用可注入工厂变得非常简单,避免了太多重复代码。这段代码允许注入继承,使用带注释的注入等等。选中此项:

    第一步 为所有angular Controller\Directions\services-InjectableClient声明基类其主要任务-将所有注入的参数设置为“this”的属性。可以覆盖此行为,请参见下面的示例

    class InjectionClient {
    
        constructor(...injected) {
            /* As we can append injections in descendants we have to process only injections passed directly to current constructor */ 
            var injectLength = this.constructor.$inject.length;
            var injectedLength = injected.length;
            var startIndex = injectLength - injectedLength;
            for (var i = startIndex; i < injectLength; i++) {
                var injectName = this.constructor.$inject[i];
                var inject = injected[i - startIndex];
                this[injectName] = inject;
            }
        }
    
        static inject(...injected) {
            if (!this.$inject) { 
                this.$inject = injected; 
            } else {
                this.$inject = injected.concat(this.$inject);
            }
        };
    }
    
    第三步 现在我们可以声明尽可能多的指令类。有继承权。我们可以用扩展数组简单地设置注入(只是别忘了调用超级方法)。见示例:

    class DirectiveFirst extends Directive {
    }
    
    DirectiveFirst.inject('injA', 'injB', 'injC');
    
    
    class DirectiveSecond extends DirectiveFirst {
    
        constructor(injD, ...injected) {
            super(...injected);
            this.otherInjectedProperty = injD;
        }
    }
    // See appended injection does not hurt the ancestor class
    DirectiveSecond.inject('injD');
    
    class DirectiveThird extends DirectiveSecond {
    
        constructor(...injected) {
            // Do not forget call the super method in overridden constructors
            super(...injected);
        }
    }    
    
    最后一步 现在,以简单的方式向angular注册指令:

    angular.directive('directiveFirst', DirectiveFirst.factory());
    angular.directive('directiveSecond', DirectiveSecond.factory());
    angular.directive('directiveThird', DirectiveThird.factory());
    
    export default function archiveTreeDirective() {
        'ngInject';
    
        return {
            restrict: 'E',
            scope: {
                selectedNodes: "="
            },
            templateUrl: 'app/components/directives/archiveTree/archiveTree.html',
            controller: ArchiveTreeController,
            controllerAs: 'vm',
            bindToController: true
        };
    }
    
    class ArchiveTreeController {
        constructor() {
            'ngInject';
            ...
        }
        ...
    }
    
    现在测试代码:

    var factoryFirst = DirectiveFirst.factory();
    var factorySec = DirectiveSecond.factory();
    var factoryThird = DirectiveThird.factory();
    
    
    var directive = factoryFirst('A', 'B', 'C');
    console.log(directive.constructor.name + ' ' + JSON.stringify(directive));
    
    directive = factorySec('D', 'A', 'B', 'C');
    console.log(directive.constructor.name + ' ' + JSON.stringify(directive));
    
    directive = factoryThird('D', 'A', 'B', 'C');
    console.log(directive.constructor.name + ' ' + JSON.stringify(directive));
    
    这将返回:

    DirectiveFirst {"injA":"A","injB":"B","injC":"C"}
    DirectiveSecond {"injA":"A","injB":"B","injC":"C","otherInjectedProperty":"D"}
    DirectiveThird {"injA":"A","injB":"B","injC":"C","otherInjectedProperty":"D"}
    
    我的解决方案:

    class myDirective {
       constructor( $timeout, $http ) {
           this.restrict = 'E';
           this.scope = {};
    
           this.$timeout = $timeout;
           this.$http = $http;
       }
       link() {
           console.log('link myDirective');
       }
       static create() {
           return new myDirective(...arguments);
       }
    }
    
    myDirective.create.$inject = ['$timeout', '$http'];
    
    export { myDirective }
    
    在主应用程序文件中

    app.directive('myDirective', myDirective.create)
    

    我刚才遇到了这个问题,我看到了这个话题。尝试了讨论中提供的一些方法,我最终以一种非常简单的方式解决了这个问题:

    angular.directive('directiveFirst', DirectiveFirst.factory());
    angular.directive('directiveSecond', DirectiveSecond.factory());
    angular.directive('directiveThird', DirectiveThird.factory());
    
    export default function archiveTreeDirective() {
        'ngInject';
    
        return {
            restrict: 'E',
            scope: {
                selectedNodes: "="
            },
            templateUrl: 'app/components/directives/archiveTree/archiveTree.html',
            controller: ArchiveTreeController,
            controllerAs: 'vm',
            bindToController: true
        };
    }
    
    class ArchiveTreeController {
        constructor() {
            'ngInject';
            ...
        }
        ...
    }
    
    我直接使用函数作为.directive('directiveName',factory)参数,并将其导出,然后在模块声明中导入
    export default function archiveTreeDirective() {
        'ngInject';
    
        return {
            restrict: 'E',
            scope: {
                selectedNodes: "="
            },
            templateUrl: 'app/components/directives/archiveTree/archiveTree.html',
            controller: ArchiveTreeController,
            controllerAs: 'vm',
            bindToController: true
        };
    }
    
    class ArchiveTreeController {
        constructor() {
            'ngInject';
            ...
        }
        ...
    }