重构控制器的功能在不同的文件中声明的服务
正如你所说的,重构函数的一个好方法是把它们放到不同的服务中。
按照angular Service docs:
角服务是单身对象或进行常见的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步:移动功能,以自己的服务
我们将定义一个名称服务和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
指数。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.
就是这样!我们的测试仍然通过,所以我们知道一切都像魅力一样。
你可以添加一个需要访问范围的效用函数的例子吗?如果它真的是一个实用函数,应该可以重构它以不使用$ scope。否则它可能是一个指令的候选人。无论如何,很难说没有一个例子。 – Narretz
Hi @Narretz,增加了一个例子。请不要为我提供重构代码或将其转换为指令的方式,我知道如何执行这些方法,这也不是我的问题。我想知道如何将函数移动到一个单独的js文件。 tnx – Gidon
既然你不需要任何提示,那么我只是说你使用控制器的方式不是角度“最佳实践”。你可以在视图中完全编写你的例子,或者使用一个指令,甚至把函数放在一个服务中,然后把服务函数绑定到$ scope变量。不过,我不推荐它。 – Narretz