在对等angularjs控制器中重构一些重复代码以管理$ interval的想法

时间:2021-07-27 19:38:28

I have a small SPA that displays several tabs. Each tab displays operational status information about the application it's associated with. The controllers for each tab create $interval objects that make AJAX calls to the server to get status info.

我有一个小型SPA,显示几个标签。每个选项卡显示与其关联的应用程序的操作状态信息。每个选项卡的控制器创建$ interval对象,这些对象对服务器进行AJAX调用以获取状态信息。

To be a good citizen, I concluded that when one tab is visible, the $intervals for the other tabs should be disabled so that they don't make the AJAX calls. The $interval for another tab/controller would be enabled when that tab is selected.

为了成为一个好公民,我得出结论,当一个标签可见时,应禁用其他标签的$ interval,以便它们不进行AJAX调用。选择该选项卡时,将启用另一个选项卡/控制器的$ interval。

In the HTML, each of my "tab" elements has attributes like the following:

在HTML中,我的每个“tab”元素都具有如下属性:

select="selected()" deselect="deselected()"

In the controller associated with each tab, I defined those methods, and they create and cancel, respectively, the $interval associated with that tab. In one of the tabs, I have a controller for the tab, but it has an accordion with two entries, and I use "$broadcast" so that the accordion entries can manage their own $intervals.

在与每个选项卡关联的控制器中,我定义了这些方法,并分别创建和取消与该选项卡关联的$ interval。在其中一个标签中,我有一个标签的控制器,但它有一个带两个条目的手风琴,我使用“$ broadcast”,以便手风琴条目可以管理自己的$间隔。

What I don't like is that I have a handful of little methods that are almost duplicated in every controller. Each controller has a "selected" and "deselected" method, and all the components that manage their own $interval have "startInterval" and "cancelInterval" methods. In most of the tabs, all four of those are in the controller for the tab. For the one tab that uses "$broadcast", I have the "selected" and "deselected" methods in the tab controller, and the "startInterval" and "cancelInterval" methods in the accordion controllers.

我不喜欢的是我有一些在每个控制器中几乎重复的小方法。每个控制器都有一个“选定”和“取消选择”方法,管理自己的$ interval的所有组件都有“startInterval”和“cancelInterval”方法。在大多数选项卡中,所有这四个选项卡都位于选项卡的控制器中。对于使用“$ broadcast”的一个选项卡,我在选项卡控制器中有“selected”和“deselected”方法,在accordion控制器中有“startInterval”和“cancelInterval”方法。

I wish I could define "selected" and "deselected" in the parent controller of all the tabs, but make it so that those methods "call into" the associated tab controller by adding some small "registration" code in the html for the tab.

我希望我可以在所有选项卡的父控制器中定义“已选择”和“取消选择”,但要使这些方法通过在选项卡的html中添加一些小的“注册”代码来“调用”关联的选项卡控制器。

However, it's possible that saving duplication in the controller will end up with some strange looking code in the HTML.

但是,保存控制器中的重复可能会导致HTML中出现一些奇怪的代码。

Any ideas for how to do this better?

有关如何更好地做到这一点的任何想法?

3 个解决方案

#1


4  

What I do is add a helper service that configures my controller. Something like this:

我所做的是添加一个配置我的控制器的帮助程序服务。像这样的东西:

angular.module('myModule').service("controllerHelper", function() {

  this.configController = function(controller) {
    controller.oneCommonMethod = function() {/*Some common code*/};
    controller.twoCommonMethod = function() {/*Some more common code*/};
  }

});

angular.module('myModule').controller("myController", function($scope, controllerHelper) {

  controllerHelper.configController(this);

});

You can also share state between the controller that call this helper service to accomplish what you want.

您还可以在调用此帮助程序服务的控制器之间共享状态以完成您想要的操作。

#2


1  

Just to play around with @Geoff Genz code

只是为了玩@Geoff Genz代码

angular.module('app', [])
                .service("controllerHelper", function() {
                    this.configController = function(scope) {
                            scope.test = 'My test';
                    }
                })
               .controller('MainCtrl',function($scope,controllerHelper){
                    controllerHelper.configController($scope);
               });

If for instance you have got a crud needs a datepicker config you can exploit this code

例如,如果你有一个crud需要一个datepicker配置,你可以利用这个代码

Update

更新

Imo the code above go against oop encapsulation principle

Imo上面的代码违反了oop封装原则

#3


0  

Ok, I didn't quite use this advice directly, but I imagine my solution has some of this feel.

好吧,我没有直接使用这个建议,但我想我的解决方案有一些这种感觉。

I changed my HTML for each to the following:

我将每个HTML更改为以下内容:

select="selected(this)" deselect="deselected(this)"

I then defined an app-wide controller with these elements:

然后我用这些元素定义了一个app范围的控制器:

$scope.tabsOpened   = {};

$scope.deselected   =
    function(ctrl) {
        ctrl.tabClosed();
        delete $scope.tabsOpened[ctrl];
    };
$scope.selected     =
    function(ctrl) {
        ctrl.tabOpened();
        $scope.tabsOpened[ctrl] = ctrl;
    };

$scope.$on('$destroy', function() {
    for (var ctrl in tabsOpened) {
        if ($scope.tabsOpened.hasOwnProperty(ctrl))
            ctrl.tabClosed();
    }
});

In the controller for each tab I defined "tabOpened" and "tabClosed" functions in each scope. That leaves it up to each tab's controller to do its setup and cleanup. Notice that I also handle the $destroy event in the top controller, and tell each tab to clean up.

在每个选项卡的控制器中,我在每个范围中定义了“tabOpened”和“tabClos​​ed”函数。这使得每个选项卡的控制器都可以进行设置和清理。请注意,我还处理顶部控制器中的$ destroy事件,并告诉每个选项卡清理。

#1


4  

What I do is add a helper service that configures my controller. Something like this:

我所做的是添加一个配置我的控制器的帮助程序服务。像这样的东西:

angular.module('myModule').service("controllerHelper", function() {

  this.configController = function(controller) {
    controller.oneCommonMethod = function() {/*Some common code*/};
    controller.twoCommonMethod = function() {/*Some more common code*/};
  }

});

angular.module('myModule').controller("myController", function($scope, controllerHelper) {

  controllerHelper.configController(this);

});

You can also share state between the controller that call this helper service to accomplish what you want.

您还可以在调用此帮助程序服务的控制器之间共享状态以完成您想要的操作。

#2


1  

Just to play around with @Geoff Genz code

只是为了玩@Geoff Genz代码

angular.module('app', [])
                .service("controllerHelper", function() {
                    this.configController = function(scope) {
                            scope.test = 'My test';
                    }
                })
               .controller('MainCtrl',function($scope,controllerHelper){
                    controllerHelper.configController($scope);
               });

If for instance you have got a crud needs a datepicker config you can exploit this code

例如,如果你有一个crud需要一个datepicker配置,你可以利用这个代码

Update

更新

Imo the code above go against oop encapsulation principle

Imo上面的代码违反了oop封装原则

#3


0  

Ok, I didn't quite use this advice directly, but I imagine my solution has some of this feel.

好吧,我没有直接使用这个建议,但我想我的解决方案有一些这种感觉。

I changed my HTML for each to the following:

我将每个HTML更改为以下内容:

select="selected(this)" deselect="deselected(this)"

I then defined an app-wide controller with these elements:

然后我用这些元素定义了一个app范围的控制器:

$scope.tabsOpened   = {};

$scope.deselected   =
    function(ctrl) {
        ctrl.tabClosed();
        delete $scope.tabsOpened[ctrl];
    };
$scope.selected     =
    function(ctrl) {
        ctrl.tabOpened();
        $scope.tabsOpened[ctrl] = ctrl;
    };

$scope.$on('$destroy', function() {
    for (var ctrl in tabsOpened) {
        if ($scope.tabsOpened.hasOwnProperty(ctrl))
            ctrl.tabClosed();
    }
});

In the controller for each tab I defined "tabOpened" and "tabClosed" functions in each scope. That leaves it up to each tab's controller to do its setup and cleanup. Notice that I also handle the $destroy event in the top controller, and tell each tab to clean up.

在每个选项卡的控制器中,我在每个范围中定义了“tabOpened”和“tabClos​​ed”函数。这使得每个选项卡的控制器都可以进行设置和清理。请注意,我还处理顶部控制器中的$ destroy事件,并告诉每个选项卡清理。