每次加载某些页面时调用一次方法(AngularJS)

时间:2014-07-24 15:50:40

标签: angularjs angularjs-directive

我有一个自定义表单指令,每个页面可能会多次使用。我需要这些指令的总数,所以在指令配置对象之外添加了一个,即

module.directive("customInput", [
    function ()
    {
        /*
         * Because each instance of the directive will get its own
         * instance of the return object, we have to declare groupCount
         * here, instead of inside the post-link function where it's used.
         */
        var groupCount = {};

        return { ...configObj... }
    }
]);

问题是此计数在视图中仍然存在。我将它移动到一个服务并给它一个重置方法,但我需要一种方法来每页只调用一次该方法。

我不想添加$routeChangeSuccess侦听器,因为对于使用这些输入的几个页面而言,这似乎太过沉重。我无法在指令的控制器中执行此操作(例如$watch("$viewContentLoaded")),因为它会执行多次。

如果有办法做一次,我不想把负担放在个别视图控制器上。有没有(可能有“父”指令)?

3 个答案:

答案 0 :(得分:1)

这可以在架构层面解决,AngularJS有很好的机制来处理这类事情。了解移动应用程序的常用编写方式,并制作“经理”服务。 Angular中的服务是一个单例,因此它可以维护变量,如对象集合(指令)和这些项的计数。然后可以在需要时询问它们,可以要求它们创建/更改/删除它们。当您执行类似ngRepeat的操作时,它也可以是数据源,而不是将数据直接存储在控制器中。

通信驱动的模型做了很多,而且效果很好。假设你有一个假设的“好友列表”。你可以这样做:

angular
  .module('myApp', [])
  .controller('MainDisplay', function($scope, buddyManager) {
    $scope.buddyManager = buddyManager;

    // Handle things here that are relevant to the main display
    $scope.sendMessage = function(buddy) {
      alert('here I could message ' + buddy.name);
    }

    buddyManager.addBuddy('Susan');
    buddyManager.addBuddy('David');
    buddyManager.addBuddy('Jamie');
  })
  .service('buddyList', function() {
    var self = this;

    this.buddies = [];
    this.buddyCount = 0; // If you didn't want to just do buddies.length...

    this.addBuddy = function(name) {
      // Again, if you didn't want to just use .length...
      self.buddyCount++;
      self.buddies.push({
        name: name
      });
    };
  })
  .directive('buddy', function() {
    return {
      restrict: 'E',
      replace: true,
      scope: { buddy: '=' },
      template: '<div class="buddy">{{ name }}</div>',
      link: function($scope) {
        // Here you can put anything specific to a buddy, like click handlers
        // $scope.buddy is yourself / your buddy data
      }
    };
  });

一个简单的页面:

<html ng-app="myApp">
<head>
<!-- You know you what you need... -->
</head>
<body ng-controller="MainDisplay">
  <buddy ng-repeat="buddy in buddyManager.buddies" buddy="buddy"></buddy>
</body>
</html>

在这里工作Plnkr: http://plnkr.co/edit/R3QMwLxEbqMRlBg74dOi?p=preview

答案 1 :(得分:0)

如果需要,您可以监听范围,只是增加。类似的东西:

module.directive("customInput", [
    function (){
        /*
         * Because each instance of the directive will get its own
         * instance of the return object, we have to declare groupCount
         * here, instead of inside the post-link function where it's used.
         */
        var groupCount = {};

        var totalCount = 0;

        return {
            link: function(scope){
                totalCount++;
                scope.$on("$destroy", function(){
                    totalCount--
                });
            }
        }
    }
]);

totalCount将始终是您拥有的元素数量。如果你想使用它,你可以连接到你想要的任何东西(服务等......)。

答案 2 :(得分:0)

我把计数器放在一个服务中,以便它有一些很好的增量和减量方法。根据{{​​3}}建议使用$destroy,我可以调用服务的减量方法。我的估计是这个解决方案比一次性重置呼叫稍微重一点,但不像手表路线变化那样糟糕。

// recommended var name for this object: groupControl
module.service("GroupControlSvc", [
    function ()
    {
        this.groupCount = {};

        this.incrementGroupCount = function (groupName)
        {
            if (!this.groupCount.hasOwnProperty(groupName)) {
                this.groupCount[groupName] = 0;
            }
            this.groupCount[groupName]++;
        };

        this.decrementGroupCount = function (groupName)
        {
            if (this.groupCount.hasOwnProperty(groupName)) {
                console.log("decrementing group " + groupName);
                this.groupCount[groupName]--;

                if (this.groupCount[groupName] === 0) {
                    console.log("removing group " + groupName);
                    delete this.groupCount[groupName];
                }
            }
        };
    }
]);


module.directive("customInput", [
    function ()
    {
        return {
            ...
            ,link: function (scope, elem, attrs)
            {
                ...

                /*
                 * Count the members of each group, so we can
                 * determine which element is last. Because
                 * groupCount is an object (and an object of
                 * objects, at that), assigning it to scope
                 * here is by reference. Thus, every scope
                 * instance will point to the same object.
                 */
                if (attrs.hasOwnProperty("editGroup")) {
                    groupControl.incrementGroupCount(attrs.editGroup);
                }
                scope.groupCount = groupControl.groupCount;

                scope.$on("$destroy", function ()
                {
                    groupControl.decrementGroupCount(attrs.editGroup);
                });
            } // end post-link function
        };
    }
]);

我想不直接公开groupCount属性,但是将范围内的getter函数赋值给它并不值得。

这也使我groupCount或其回调失败导致$destroy出现偏差的可能性。

虽然这解决了我的需要,但它没有回答问题。