我怎样才能添加一些小的实用功能到我的 AngularJS 应用程序?

我想添加一些实用功能到我的 AngularJS 应用程序。例如:

$scope.isNotString = function (str) {
return (typeof str !== "string");
}

将它们添加为服务的最佳方式是什么?据我所知,我可以做到 但是我想在我的 HTML 页面中使用这些,所以它仍然是可能的,如果 例如,我可否使用以下方法:

 <button data-ng-click="doSomething()"
data-ng-disabled="isNotString(abc)">Do Something
</button>

有人能给我一个例子,我可以如何添加这些。我应该创建一个服务 或者有其他的方法来做到这一点。最重要的是,我希望这些实用程序 在一个文件中的函数,而不是与另一部分的主要设置组合。

我知道有一些解决方案,但没有一个是那么清楚的。

解决方案1 -由 Urban 提出

$scope.doSomething = ServiceName.functionName;

这里的问题是我有20个函数和10个控制器。如果我这样做,就意味着向每个控制器添加大量代码。

解决方案2 -由我提出

    var factory = {


Setup: function ($scope) {


$scope.isNotString = function (str) {
return (typeof str !== "string");
}

这样做的缺点是,在每个控制器开始时,我会对每个传递 $scope 的服务进行一个或多个这样的 Setup 调用。

解决方案3 -由 Urban 提出

Urban 提出的创建通用服务的解决方案看起来不错:

var app = angular
.module('app', ['ngAnimate', 'ui.router', 'admin', 'home', 'questions', 'ngResource', 'LocalStorageModule'])
.config(['$locationProvider', '$sceProvider', '$stateProvider',
function ($locationProvider, $sceProvider, $stateProvider) {


$sceProvider.enabled(false);
$locationProvider.html5Mode(true);

我应该将通用服务添加到这里吗? 我如何才能做到这一点?

108753 次浏览

编辑7/1/15:

我很久以前就写了这个答案,有一段时间没有跟上角度,但似乎这个答案仍然相对受欢迎,所以我想指出,下面@nicolas 提出的一些观点是好的。例如,注入 $rootScope 并在其中附加帮助程序将使您不必为每个控制器添加它们。另外-我同意,如果你添加的应该被认为是角服务或过滤器,他们应该采用这种方式的代码。

此外,在当前版本1.4.2中,Angular 公开了一个“ Provider”API,允许将其注入到配置块中。更多信息参见以下资源:

Https://docs.angularjs.org/guide/module#module-loading-dependencies

Module.config 中的 AngularJS 值依赖注入

我不认为我会更新下面的实际代码块,因为这些天我并没有真正积极地使用 Angular,而且我也不想冒险得到一个新的答案,除非它确实符合新的最佳实践。如果其他人觉得可以胜任,那就尽管去做吧。

编辑2/3/14:

在思考了这个问题并阅读了其他一些答案之后,我实际上认为我更喜欢@Brent Washburne 和@Amogh Talpallikar 提出的方法的一个变体。特别是如果您正在寻找像 isNotString ()或类似的实用程序。这里的一个明显优势是,您可以在有角度的代码之外重用它们,并且可以在配置函数中使用它们(对服务不能这样做)。

也就是说,如果您正在寻找一种通用的方法来重用应该是服务的东西,我认为旧的答案仍然是一个很好的答案。

我现在要做的是:

App.js:

var MyNamespace = MyNamespace || {};


MyNamespace.helpers = {
isNotString: function(str) {
return (typeof str !== "string");
}
};


angular.module('app', ['app.controllers', 'app.services']).
config(['$routeProvider', function($routeProvider) {
// Routing stuff here...
}]);

Js:

angular.module('app.controllers', []).
controller('firstCtrl', ['$scope', function($scope) {
$scope.helpers = MyNamespace.helpers;
});

然后在你的部分中你可以使用:

<button data-ng-click="console.log(helpers.isNotString('this is a string'))">Log String Test</button>

老答案如下:

最好将它们作为服务包括在内。如果您打算在多个控制器之间重复使用它们,将它们作为服务包括在内,将使您不必重复编写代码。

如果您希望在 html 部分中使用服务函数,那么您应该将它们添加到该控制器的作用域中:

$scope.doSomething = ServiceName.functionName;

然后在你的部分中你可以使用:

<button data-ng-click="doSomething()">Do Something</button>

这里有一个方法,你可以让这一切井井有条,免于太多的麻烦:

将控制器、服务和路由代码/config 分成三个文件: controller. js、 services.js 和 app.js。顶层模块是“ app”,它具有 app.controller 和 app.services 作为依赖项。然后,app.controller 和 app.services 可以在它们自己的文件中声明为模块。下面的组织结构来自美国广播公司(角形种子) :

App.js:

 angular.module('app', ['app.controllers', 'app.services']).
config(['$routeProvider', function($routeProvider) {
// Routing stuff here...
}]);

服务 js:

 /* Generic Services */
angular.module('app.services', [])
.factory("genericServices", function() {
return {
doSomething: function() {
//Do something here
},
doSomethingElse: function() {
//Do something else here
}
});

Js:

angular.module('app.controllers', []).
controller('firstCtrl', ['$scope', 'genericServices', function($scope, genericServices) {
$scope.genericServices = genericServices;
});

然后在你的部分中你可以使用:

<button data-ng-click="genericServices.doSomething()">Do Something</button>
<button data-ng-click="genericServices.doSomethingElse()">Do Something Else</button>

这样,您只需向每个控制器添加一行代码,并且能够访问任何可访问范围的服务函数。

添加实用程序函数的最简单方法是将它们保留在全局级别:

function myUtilityFunction(x) { return "do something with "+x; }

然后,添加实用程序函数(到控制器)的最简单方法是将其分配给 $scope,如下所示:

$scope.doSomething = myUtilityFunction;

然后你可以这样称呼它:

\{\{ doSomething(x) }}

或者像这样:

ng-click="doSomething(x)"

编辑:

最初的问题是,添加实用功能的最佳方式是否是通过服务。如果函数足够简单(如 OP 提供的 isNotString()示例) ,我会说不。

编写服务的好处是可以用另一个服务(通过注入)替换它,以便进行测试。走到极端,你需要注入每一个单一的实用功能到您的控制器?

文档说明只需简单地定义控制器中的行为(如 $scope.double) : http://docs.angularjs.org/guide/controller

我是否正确地理解了您只是想定义一些实用工具方法并使它们在模板中可用?

您不必将它们添加到每个控制器中。只需为所有实用程序方法定义一个控制器,并将该控制器附加到 < html > 或 < body > (使用 ngController 指令)。在 < html > (意味着任何地方,句点)或 < body > (除了 < head > 之外的任何地方)下附加的任何其他控制器都将继承该 $scope,并且可以访问这些方法。

说到这个老话题,我想强调一下

1 °)效用函数可能(应该?)通过 module.run 添加到 rootscope。不需要为此实例化特定的根级控制器。

angular.module('myApp').run(function($rootScope){
$rootScope.isNotString = function(str) {
return (typeof str !== "string");
}
});

2 °)如果你把代码组织成单独的模块,你应该使用角度 服务或者 工厂,然后把它们注入到传递给 run 块的函数中,如下所示:

angular.module('myApp').factory('myHelperMethods', function(){
return {
isNotString: function(str) {
return (typeof str !== 'string');
}
}
});


angular.module('myApp').run(function($rootScope, myHelperMethods){
$rootScope.helpers = myHelperMethods;
});

3 °)我的理解是,在视图中,在大多数情况下,你需要这些辅助函数来对你显示的字符串应用某种格式。在最后一种情况下,您需要的是使用角 过滤器

如果你已经将一些底层的辅助方法结构化为角度服务或工厂,只需将它们注入到你的过滤器构造函数中:

angular.module('myApp').filter('myFilter', function(myHelperMethods){
return function(aString){
if (myHelperMethods.isNotString(aString)){
return
}
else{
// something else
}
}
);

在你看来:

\{\{ aString | myFilter }}

为什么不使用控制器继承,HeaderCtrl 作用域中定义的所有方法/属性都可以在 ng-view 中的控制器中访问。在所有控制器中都可以访问 $scope.servHelper。

    angular.module('fnetApp').controller('HeaderCtrl', function ($scope, MyHelperService) {
$scope.servHelper = MyHelperService;
});




<div ng-controller="HeaderCtrl">
<div ng-view=""></div>
</div>

您也可以这样使用常量服务。在常量调用之外定义函数也允许它是递归的。

function doSomething( a, b ) {
return a + b;
};


angular.module('moduleName',[])
// Define
.constant('$doSomething', doSomething)
// Usage
.controller( 'SomeController', function( $doSomething ) {
$scope.added = $doSomething( 100, 200 );
})
;

下面是我使用的一个简单、紧凑、容易理解的方法。
首先,在 js 中添加一个服务。

app.factory('Helpers', [ function() {
// Helper service body


var o = {
Helpers: []


};


// Dummy function with parameter being passed
o.getFooBar = function(para) {


var valueIneed = para + " " + "World!";


return valueIneed;


};


// Other helper functions can be added here ...


// And we return the helper object ...
return o;


}]);

然后,在控制器中注入 helper 对象并使用任何可用的函数,如下所示:

app.controller('MainCtrl', [


'$scope',
'Helpers',


function($scope, Helpers){


$scope.sayIt = Helpers.getFooBar("Hello");
console.log($scope.sayIt);


}]);