【问题标题】:Which parameters to pass into Angular JS custom directive controller?将哪些参数传递给 Angular JS 自定义指令控制器?
【发布时间】:2015-04-14 15:01:54
【问题描述】:

我正在尝试创建一个需要使用单独控制器的自定义指令,因为它需要具有可由子指令调用的函数。

到目前为止,这是我的代码:

angular.module('myDirectives').controller('SlideInMenuController', function ($scope, $element, $attrs) {

    $scope.isOpen = false;

    // Toggle Function
    this.toggle = function(){

        $scope.$apply(function(){
            $scope.isOpen = !$scope.isOpen;
        });

    };


    // Watch $scope.isOpen and open the menu
    $scope.$watch('isOpen', function() {

        if($scope.isOpen == true){
            $element.attr('is-open', true);
        }
        else{
            $element.attr('is-open', false);
        }

        return false;

    });

}

angular.module('myDirectives').directive('slideInMenu', function ($swipe) {

    return {

        restrict: 'EA',
        scope: {},
        controller:'SlideInMenuController'        

    };

});


angular.module('myDirectives').directive('slideInMenuToggle', function ($swipe) {

    return {

        restrict: 'EA',
        require: '^slideInMenu',

        link: function ($scope, $element, $attrs, SlideInMenuCtrl) {

            $element.bind('click', function(){
                SlideInMenuCtrl.toggle();
            });

        }        

    };

});

(注意:我使用的是 ng-annotate,所以我不必将所有依赖项都写两次)

我需要将 $swipe 服务注入指令控制器,但普通控制器不会将 $scope、$element、$attrs 作为前三个参数。这让我想知道我是否应该将它们放入链接函数并在那里做 DOM 的东西,但如果我这样做,控制器中的内容和链接函数中的内容。

我已经阅读了许多博客和 SO 答案,其中说明了编译/链接/控制器的运行顺序,但仍然找不到关于我上面的示例应该去哪里的明确答案。

任何帮助将不胜感激。

【问题讨论】:

  • “我需要注入 $swipe 服务”:继续,这完全合理。 “但普通控制器不会......”:您的控制器是旨在由指令使用的控制器;再次完全合理地依赖于指令特定的东西。 (顺便说一句,上面的代码没有使用$attrs,你可以删除它。)你的实现对我来说似乎很好——除了一件事:我宁愿从element.bind调用$apply,它在Angular外部调用而不是来自SlideInMenuController.toggle。还是我错过了一点?
  • 因此,通常依赖项可以按任何顺序注入。我认为 $scope、$element 和 $attrs 的顺序必须正确,因为它们是正常的函数参数,而不是注入的依赖项。如果它们就像任何其他依赖项一样,那么它们可以按任何顺序排列,例如 ($swipe, $element, $scope)?如果是这样,那么为什么有些人在没有美元符号的情况下调用它们(范围、元素、属性)?
  • 至于$scope.$apply,我不完全明白为什么我把它放在我放的地方。我只知道我必须把它放在那里才能让它工作;-)如果你认为这更有意义,我可以尝试将它移动到切换指令中的绑定。
  • 嗨,请参阅 Werlang 答案中的有效点,并且:1)是的,link 函数需要按特定顺序的参数。控制器按您要求的顺序注入依赖项。并且名称无关紧要,您可以使用 ['$http', function($q) {...}]$q 将是 $http 服务(如果您喜欢痛苦,这是一个不错的选择,例如 C 中的 #define TRUE FALSE :)
  • 2) 对于$apply:是的,对我来说更有意义:bind 是从 Angular 外部(直接从浏览器)调用的。它必须通知 Angular 才能进行脏检查。原则上,控制器的方法可以从 Angular 内部调用。在这种情况下,您将收到digest already in progress 错误。

标签: javascript angularjs


【解决方案1】:

AngularJS 有两种函数。两者都不打算直接调用。

1) Injectables:接收参数的函数,其名称(除了少数例外)必须在 dependency injection 子系统中注册。 这就是 ng-annotate 存在的原因。您也可以对这些使用数组表示法。

angular.module('stackOverflow').service('answer', ['myService', function(myService) {
...
}]);

一些示例是您传递给angular.module() 函数的示例,例如service()factory()directive()controller()

2) 普通函数。这些没有特殊处理,它是普通的 JavaScript。它们被传递给指令定义对象中的链接和编译槽。

如果最右边的参数没有用,你可以省略它们,但不能省略其他参数。由于参数的顺序是固定的,您不能重新排序它们。但是您可以随意称呼它们

函数就是这样。

关于使用 $ 的约定:小心! AngularJS 内置服务以 $ 为前缀,因此您应该以这种方式为可注入函数命名参数。对于所有其他情况,不要以 $ 为前缀:您自己的函数和位置参数,就像您在 link() 和 compile() 中看到的那样。 在这些函数中使用 $ 前缀具有误导性和不良指导作用

为了更好地区分 compile() 和链接的参数,您可以为模板添加 ti 前缀。现在我更喜欢使用那些不带前缀的。最好让它们四处移动。

compile: function (tElement, tAttrs) {
    return function link(scope, iElement, iAttrs, ctrls) {
    };
}

【讨论】:

  • 很好的解释。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多