我想让一组控制器访问 trait 中定义的方法和属性。现在我想出的最好的实现是:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, CtrlTrait) {
$scope.name = CtrlTrait.presetName;
CtrlTrait.setGreeting.call($scope, 'Hello');
});
app.service('CtrlTrait', function() {
this.setGreeting = function(greeting) { this.greeting = greeting; }
this.presetName = 'tom';
});
普伦克尔代码
这很好,但我希望可以通过控制器的$scope访问属性和方法,而无需在每个控制器中手动创建别名。我希望能够通过将服务注入控制器来使用模板中的属性和方法。
这是否可能,或者我是否必须为$scope
(如 $specialCtrlScope
)创建一个 [包装器]/[提供程序] 来预设我想要的属性和方法?
尝试使用这样的angular.extend
: angular.extend($scope,CtrlTrait);
它将使我们能够$scope
使用与您的服务相同的功能。因此,您可以像这样直接在 html 中使用该函数:
<button ng-click="setGreeting('Good bye! ')">Good Bye</button>
这是您改编的 plunker 演示:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, CtrlTrait) {
$scope.name = CtrlTrait.presetName;
// CtrlTrait.setGreeting.call($scope, 'Hello');
angular.extend($scope,CtrlTrait);
$scope.setGreeting('Hello World');
});
app.service('CtrlTrait', function() {
this.setGreeting = function(greeting) { this.greeting = greeting; }
this.presetName = 'tom';
});
http://plnkr.co/edit/BENS78mjFfpc6VCEtgK8?p=preview
您可以在控制器中尝试以下操作
$scope.setGreeting = CtrlTrait.setGreeting
以后可以使用
$scope.setGreeting.call($scope, 'Hello');
评论后编辑
试试这个
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, CtrlTrait) {
$scope.trait = CtrlTrait;
$scope.name = $scope.trait.presetName;
$scope.trait.setGreeting.call($scope,'Hello');
});
app.service('CtrlTrait', function() {
var trait = {};
trait.setGreeting = function(greeting) { this.greeting = greeting; }
trait.presetName = 'tom';
return trait;
});
所以我会在前面加上免责声明...我不建议你真的这样做,或者至少不要以这种方式这样做。 在围绕模块化和注入构建的框架中,在控制器和服务之间添加额外的耦合,所有这些都是为了节省一些方法调用。
也就是说,这是一种实现您想要的方法。(JSFiddle在这里)
var app = angular.module('myApp', []);
var controllerMaker = function(trait,controllerCode){
return function($scope, $injector){
//'apply' traits to this scope
var apply = function(trait){
trait.applyTo($scope);
}
apply.$inject = [trait];
$injector.invoke(apply);
//Finishes the other injections
controllerCode.$inject = ['$scope'];
controllerCode($scope);
};
}
//Here's a sample 'trait'
app.service('CtrlTrait', function() {
this.applyTo = function(obj){
obj.setGreeting = function(greeting) { this.greeting = greeting; }
obj.presetName = 'tom';
}
});
//Then, setup your controller like this
app.controller('GreatController', controllerMaker("CtrlTrait",function($scope){ //Not using injection though!
$scope.bleh = $scope.presetName; //will be 'tom'
}))
这当然有弱点,比如你的控制器失去了注射,但如果你真的想这样做,我相信你可以和$inject
一起玩,找到适合你需求的东西。
如果函数是一个对象,Angular 将注入函数的返回值。 所以在你的代码中:
var app = angular.module('plunker', []);
app.controller('MainCtrl',["$scope","DefaultName","TraitService", function($scope, defaultName, traitService) {
$scope.name = defaultName;
$scope.OKPressed = function() {
traitService.setName($scope.name);
};
});
// You can use .constant() for a constant value;
app.constant("DefaultName", "tom");
app.service('TraitService', function() {
var traitService = {}; // The name does't matter
traitService.setName = function(name) {
// Not this.name = name because (this)is not guaranteed to persist or be the same across injections.
// I am only using local storage to illustrate. I usually use $rootScope to store
// Global variables. since they are always available on the $scope object without
// needing a service.
// That might be a better way for you ($rootScope)
localStorage.setItem("nameKey", name);
}
traitService.getName = function () {
return localStorage.getItem("nameKey");
}
return traitService; // This is what will be injected above
});