【问题标题】:Reusable functions or services in AngularJSAngularJS 中的可重用函数或服务
【发布时间】:2016-09-14 16:15:26
【问题描述】:

我正在为所有控制器重复相同的代码。

例如

$scope.CANCELLATION_IN_PROCESS = function(getOrder) {
    return getOrder.status == 'ORDER_PLACED' && getOrder.cancellableStatus == 'CANCELLATION_IN_PROCESS' && getOrder.returnableStatus == 'NON_RETURNABLE';
}

我们在 dom 视图中使用 CANCELLATION_IN_PROCESS 来显示/隐藏硬编码消息。

有什么办法可以优化代码。

我尝试使用服务,但无法申请查看。参数“getOrder”的问题,因为它只在视图中可用,并且在我的控制器中与服务保持未定义。

谢谢 MG

【问题讨论】:

  • 无法申请查看是什么意思?请参阅下面的答案

标签: angularjs angularjs-scope angularjs-ng-repeat


【解决方案1】:

这个函数可以附加到$rootScope:

angular.module('myModule').run(function($rootScope) {
    $rootScope.CANCELLATION_IN_PROCESS = function(getOrder) {
        return getOrder.status == 'ORDER_PLACED' && getOrder.cancellableStatus == 'CANCELLATION_IN_PROCESS' && getOrder.returnableStatus == 'NON_RETURNABLE';
    }
});

然后在应用程序模板的任何部分使用:

CANCELLATION_IN_PROCESS(order)

【讨论】:

  • 坏坏的解决方案。范围不应包含逻辑。范围应尽可能用于将视图与模型绑定。参考:stackoverflow.com/questions/32761540/…
  • @DeveshSati 好坏取决于具体情况。此解决方案是最简单的解决方案,如果使用得当,效果会很好。您提供的解决方案并没有太大的不同,因为它使用控制器作用域而不是 rootScope。好的做法是使用控制器本身(vm = this)。
【解决方案2】:

将方法移动到应用程序顶部的基本控制器(如果需要,创建),并使用controllerAs 语法。将其命名为 baseCtrl 并在 html 中使用 baseCtrl.CANCELLATION_IN_PROCESS

【讨论】:

    【解决方案3】:

    好吧,如果您想重用和抽象控制器中的逻辑,那么在我看来,要走的路就是服务。由于服务是单例的,因此不会为您使用它的每个控制器一次又一次地创建该函数。

    要在视图中使用服务方法,您必须将服务方法与范围方法绑定,如果使用 controllerAs 语法,则必须绑定 ViewModel。

    类似这样的:

    .service('statusService',function(){
         this.CANCELLATION_IN_PROCESS = function(getOrder) {
            return getOrder.status == 'ORDER_PLACED' && getOrder.cancellableStatus == 'CANCELLATION_IN_PROCESS' && getOrder.returnableStatus == 'NON_RETURNABLE';
         }
    

    现在在每个使用它的控制器中注入服务,并绑定到视图。像这样:

    .controller('xyz',function($scope,statusService){
        $scope.cancellation_in_process=statusService.CANCELLATION_IN_PROCESS;
    });
    

    您的视图将与以前一样。但是,这是一种更 DRY 的方式,逻辑(或模型)位于服务中。控制器只是将视图连接到模型。由于服务是单例的,因此逻辑被重用,而不是为每个控制器重新创建

    【讨论】:

      【解决方案4】:

      执行此操作的一种方法是将函数放置在主控制器中。 默认情况下,子控制器继承自主控制器范围,因此当您从子控制器调用该函数时,该函数将可用。

      像这样在masterCtrl中创建和定义函数

      app.controller('mainCtrl', ['$scope', function ($scope) {
      
          $scope.CANCELLATION_IN_PROCESS = function(getOrder) {
              return getOrder.status == 'ORDER_PLACED' && getOrder.cancellableStatus == 'CANCELLATION_IN_PROCESS' && getOrder.returnableStatus == 'NON_RETURNABLE';
          }
      }]);
      

      应用这个或类似的结构来构建 masterCtrl 包裹在其他控制器周围的 html

      <body ng-controller="masterCtrl">
      
          <div ng-controller="childCtrl1">
          ....
          <a ng-click="CANCELLATION_IN_PROCESS(yourOrder)">Test</a>
          ....
      
          <div ng-controller="childCtrl2">
          ....
      

      如果您需要在控制器中添加自定义版本的 CANCELLATION_IN_PROCESS 函数,则只需在该控制器中添加函数并应用更改

      app.controller('childCtrl2', ['$scope', function ($scope) {
      
          $scope.CANCELLATION_IN_PROCESS = function(getOrder) {
              return getOrder.status == 'ORDER_PLACED in child';
          }
      }]);
      

      【讨论】:

        【解决方案5】:

        我不知道你的确切代码,所以这里有一些虚拟的 sn-ps 可能适合你的需求

        这是用于服务的虚拟 sn-p

        .factory('factory_name', function() {
            var obj = {};
            var ObjFactory = {
               obj : obj
            }
        });
        

        这是控制器的虚拟 sn-p

        .controller('controller_name', function(factory_name) {
            $scope.obj = factory_name.obj;
        });
        

        现在您的 $scope.obj 可以访问该工厂的所有功能 你可以像控制器函数一样从视图中调用它

        【讨论】:

          猜你喜欢
          • 2013-08-06
          • 2023-03-12
          • 1970-01-01
          • 2016-05-18
          • 2015-07-14
          • 1970-01-01
          • 1970-01-01
          • 2015-07-12
          • 2015-12-07
          相关资源
          最近更新 更多