在Angular中分离脚本

时间:2013-10-21 12:30:39

标签: angularjs design-patterns

我创建了一个具有以下结构的角度应用程序。 应用程序配置,路由,指令,控制器和过滤器都在index.js中定义(我知道不建议这样做)。我的所有常规函数都在一个名为main.js的控制器中,这也是我在index.html的主视图中使用的控制器。从那时起,该应用程序由10个不同的视图组成,每个视图都有自己的控制器。

main.js变得非常难以维护,因此我想将其分成五个外部“实用程序”样式文件,其中包含应用程序使用的常规功能。这些函数都使用angular的$ scope,并且必须能够被应用程序中存在的所有视图和控制器访问。

在过去的几天里,我尝试了几种不同的方法,例如在angular的工厂服务下定义函数,使用angular的$ provide方法,定义没有视图的控制器和许多其他方法。他们都没有为我工作。将main.js中存在的函数与外部js文件分开的最简单方法是什么?更改函数本身内的任何代码。让我们假装该函数不能转换为指令。

示例 - 检查用户名为“guest”字符串并返回图像的函数

main.js -

$scope.defaultpic = function(username) {
        var guest = username;
        if (guest.indexOf("guest") != -1){
            {return {"background-image": "url('data:image/png;base64,chars"}}
        }
    }
视图中的

<img ng-style="defaultpic(JSON.Value)" class="user_pic" ng-src="getprofilepic/{{JSON.Value}}"/>

干杯, 吉登

2 个答案:

答案 0 :(得分:1)

为了在标记中使用该功能,您仍然必须将其绑定到范围。但是,您可以将函数体移动到服务:

angular.module('myapp').factory('picService',[ function () {
    return {
        defaultpic: function(username) {
            var guest = username;
            if (guest.indexOf("guest") != -1){
                {return {"background-image": "url('data:image/png;base64,chars"}}
            }
        }
    };
}]);

然后将其绑定在控制器中:

$scope.defaultpic = picService.defaultpic;

答案 1 :(得分:1)

重构控制器作为在不同文件中声明的服务

正如您所说,重构函数的一个好方法是将它们放入不同的服务中。

根据angular Service docs

  

Angular服务是执行Web应用程序通用特定任务的单例对象或函数。

以下是一个例子:

原始代码

这里我们有一个简单的Hello World应用程序,其控制器有两个功能:greet()getName()

app.js

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.getName = function () {
    return 'World';
  }

  $scope.greet = function (name) {
    return 'Hello ' + name;
  };
});

的index.html

...
<div id="container" ng-controller="MainCtrl">
  <h1>{{greet(getName())}}</h1>
</div>
...

我们想测试我们的范围总是有两个函数,所以我们知道它正在按预期工作,所以我们将编写两个简单的茉莉花测试:

appSpec.js

describe('Testing a Hello World controller', function() {
  var $scope = null;
  var ctrl = null;

  //you need to indicate your module in a test
  beforeEach(module('plunker'));

  beforeEach(inject(function($rootScope, $controller) {
    $scope = $rootScope.$new();

    ctrl = $controller('MainCtrl', {
      $scope: $scope
    });
  }));

  it('should say hallo to the World', function() {
    expect($scope.getName()).toEqual('World');
  });

  it('shuld greet the correct person', function () {
    expect($scope.greet('Jon Snow')).toEqual('Hello Jon Snow');
  })
});

Check it out in plnkr

步骤1:将控制器功能重构为单独的功能

为了开始将控制器与我们的函数分离,我们将在app.js中创建两个单独的函数。

app.js

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.getName = getName;

  $scope.greet = greet;
});

function getName() {
  return 'World';
}

function greet(name) {
  return 'Hello ' + name;
}

现在我们检查测试输出,看到一切正常。

Check out the plnkr for step 1

第2步:将功能移至自己的服务

我们将定义一个NameService和GreetService,将我们的函数放入其中,然后在我们的控制器中将服务定义为依赖项。

app.js

var app = angular.module('plunker', []);

app.service('NameService', function () {
  this.getName = function getName() {
    return 'World';
  };
});

app.service('GreetService', function() {
  this.greet = function greet(name) {
    return 'Hello ' + name;
  }
});

app.controller('MainCtrl', ['$scope', 'NameService', 'GreetService', function($scope, NameService, GreetService) {
  $scope.getName = NameService.getName;

  $scope.greet = GreetService.greet;
}]);

我们确保我们的测试仍然是绿色的,因此我们可以继续进行最后一步。

Have a look at step 2 in plunker

最后一步:将我们的服务放在不同的文件中

最后,我们将生成两个文件,NameService.js和GreetService.js,并将我们的服务放入其中。

NameService.js

angular.module('plunker').service('NameService', function () {
  this.getName = function getName() {
    return 'World';
  };
});

GreetService.js

angular.module('plunker').service('GreetService', function() {
  this.greet = function greet(name) {
    return 'Hello ' + name;
  }
});

我们还需要确保将新脚本添加到index.html

的index.html

...
<script src="NameService.js"></script>
<script src="GreetService.js"></script>
...

这就是我们的控制器现在的样子,整洁吧?

app.js

var app = angular.module('plunker', []);

app.controller('MainCtrl', ['$scope', 'NameService', 'GreetService', function($scope, NameService, GreetService) {
  $scope.getName = NameService.getName;

  $scope.greet = GreetService.greet;
}]);

Plunker for the final step.

就是这样!我们的测试仍然通过,所以我们知道一切都像魅力一样。