Mam trzy kontrolery, które są dość podobne. Chcę mieć kontroler, który te trzy rozszerzenia rozszerzają i dzielą jego funkcje.
Mam trzy kontrolery, które są dość podobne. Chcę mieć kontroler, który te trzy rozszerzenia rozszerzają i dzielą jego funkcje.
Odpowiedzi:
Może ty nie rozciągają kontroler ale możliwe jest rozszerzenie kontrolera lub dokonać jednego kontrolera wstawką wielu kontrolerów.
module.controller('CtrlImplAdvanced', ['$scope', '$controller', function ($scope, $controller) {
// Initialize the super class and extend it.
angular.extend(this, $controller('CtrlImpl', {$scope: $scope}));
… Additional extensions to create a mixin.
}]);
Po utworzeniu kontrolera nadrzędnego zawarta w nim logika jest również wykonywana. Aby uzyskać więcej informacji, zobacz $ controller (), ale tylko $scope
wartość musi zostać przekazana. Wszystkie pozostałe wartości zostaną wstrzyknięte normalnie.
@mwarren , twoje obawy są rozwiązywane automatycznie przez wstrzyknięcie zależności kątowej . Wszystko, czego potrzebujesz, to wstrzyknięcie $ scope, chociaż w razie potrzeby możesz zastąpić inne wstrzyknięte wartości. Weź następujący przykład:
(function(angular) {
var module = angular.module('stackoverflow.example',[]);
module.controller('simpleController', function($scope, $document) {
this.getOrigin = function() {
return $document[0].location.origin;
};
});
module.controller('complexController', function($scope, $controller) {
angular.extend(this, $controller('simpleController', {$scope: $scope}));
});
})(angular);
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.js"></script>
<div ng-app="stackoverflow.example">
<div ng-controller="complexController as C">
<span><b>Origin from Controller:</b> {{C.getOrigin()}}</span>
</div>
</div>
Chociaż dokument $ nie jest przekazywany do „simpleController”, gdy jest tworzony przez „complexController”, dokument $ jest dla nas wstrzykiwany.
$.extend()
, możesz po prostu zadzwonić$controller('CtrlImpl', {$scope: $scope});
angular.extend
(lub $.extend
) w rzeczywistości oznacza rozszerzenie $scope
jedynego, ale jeśli kontroler podstawowy również definiuje niektóre właściwości (np. this.myVar=5
), masz dostęp tylko do this.myVar
kontrolera rozszerzającego podczas używaniaangular.extend
handleSubmitClick
który zadzwoniłby, handleLogin
który z kolei miałby loginSuccess
a loginFail
. Tak więc, moim rozszerzonego kontrolera Ja wtedy miałem do przeciążenia handleSubmitClick
, handleLogin
oraz loginSucess
dla prawidłowego loginSuccess
funkcjonowania ma być używany.
Do dziedziczenia można użyć standardowych wzorców dziedziczenia JavaScript. Oto demo, które wykorzystuje$injector
function Parent($scope) {
$scope.name = 'Human';
$scope.clickParent = function() {
$scope.name = 'Clicked from base controller';
}
}
function Child($scope, $injector) {
$injector.invoke(Parent, this, {$scope: $scope});
$scope.name = 'Human Child';
$scope.clickChild = function(){
$scope.clickParent();
}
}
Child.prototype = Object.create(Parent.prototype);
Jeśli używasz controllerAs
składni (którą bardzo polecam), jeszcze łatwiej jest użyć klasycznego wzorca dziedziczenia:
function BaseCtrl() {
this.name = 'foobar';
}
BaseCtrl.prototype.parentMethod = function () {
//body
};
function ChildCtrl() {
BaseCtrl.call(this);
this.name = 'baz';
}
ChildCtrl.prototype = Object.create(BaseCtrl.prototype);
ChildCtrl.prototype.childMethod = function () {
this.parentMethod();
//body
};
app.controller('BaseCtrl', BaseCtrl);
app.controller('ChildCtrl', ChildCtrl);
Innym sposobem może być stworzenie po prostu „abstrakcyjnej” funkcji konstruktora, która będzie twoim podstawowym kontrolerem:
function BaseController() {
this.click = function () {
//some actions here
};
}
module.controller('ChildCtrl', ['$scope', function ($scope) {
BaseController.call($scope);
$scope.anotherClick = function () {
//other actions
};
}]);
Cóż, nie jestem do końca pewien, co chcesz osiągnąć, ale zazwyczaj usługi są właściwą drogą. Możesz także użyć charakterystyki dziedziczenia Scope Angulara, aby współdzielić kod między kontrolerami:
<body ng-controller="ParentCtrl">
<div ng-controller="FirstChildCtrl"></div>
<div ng-controller="SecondChildCtrl"></div>
</body>
function ParentCtrl($scope) {
$scope.fx = function() {
alert("Hello World");
});
}
function FirstChildCtrl($scope) {
// $scope.fx() is available here
}
function SecondChildCtrl($scope) {
// $scope.fx() is available here
}
$scope.$parent.fx( )
byłby o wiele czystszym sposobem na zrobienie tego, skoro tak naprawdę jest to zdefiniowane?
Nie rozbudowujesz kontrolerów. Jeśli wykonują te same podstawowe funkcje, funkcje te należy przenieść do usługi. Tę usługę można wprowadzić do kontrolerów.
Kolejne dobre rozwiązanie zaczerpnięte z tego artykułu :
// base controller containing common functions for add/edit controllers
module.controller('Diary.BaseAddEditController', function ($scope, SomeService) {
$scope.diaryEntry = {};
$scope.saveDiaryEntry = function () {
SomeService.SaveDiaryEntry($scope.diaryEntry);
};
// add any other shared functionality here.
}])
module.controller('Diary.AddDiaryController', function ($scope, $controller) {
// instantiate base controller
$controller('Diary.BaseAddEditController', { $scope: $scope });
}])
module.controller('Diary.EditDiaryController', function ($scope, $routeParams, DiaryService, $controller) {
// instantiate base controller
$controller('Diary.BaseAddEditController', { $scope: $scope });
DiaryService.GetDiaryEntry($routeParams.id).success(function (data) {
$scope.diaryEntry = data;
});
}]);
Możesz utworzyć usługę i odziedziczyć jej zachowanie w dowolnym kontrolerze, po prostu wstrzykując ją.
app.service("reusableCode", function() {
var reusableCode = {};
reusableCode.commonMethod = function() {
alert('Hello, World!');
};
return reusableCode;
});
Następnie w kontrolerze, który chcesz rozszerzyć z powyższej usługi kodu wielokrotnego użytku:
app.controller('MainCtrl', function($scope, reusableCode) {
angular.extend($scope, reusableCode);
// now you can access all the properties of reusableCode in this $scope
$scope.commonMethod()
});
DEMO PLUNKER: http://plnkr.co/edit/EQtj6I0X08xprE8D0n5b?p=preview
Możesz spróbować czegoś takiego (nie testowałem):
function baseController(callback){
return function($scope){
$scope.baseMethod = function(){
console.log('base method');
}
callback.apply(this, arguments);
}
}
app.controller('childController', baseController(function(){
}));
Możesz rozszerzyć o usługi , fabryki lub dostawców . są takie same, ale o różnym stopniu elastyczności.
tutaj przykład przy użyciu fabryki: http://jsfiddle.net/aaaflyvw/6KVtj/2/
angular.module('myApp',[])
.factory('myFactory', function() {
var myFactory = {
save: function () {
// saving ...
},
store: function () {
// storing ...
}
};
return myFactory;
})
.controller('myController', function($scope, myFactory) {
$scope.myFactory = myFactory;
myFactory.save(); // here you can use the save function
});
I tutaj możesz również użyć funkcji sklepu:
<div ng-controller="myController">
<input ng-blur="myFactory.store()" />
</div>
Możesz bezpośrednio użyć kontrolera $ („ParentController”, {$ scope: $ scope}) Przykład
module.controller('Parent', ['$scope', function ($scope) {
//code
}])
module.controller('CtrlImplAdvanced', ['$scope', '$controller', function ($scope, $controller) {
//extend parent controller
$controller('CtrlImpl', {$scope: $scope});
}]);
Możesz użyć składni Angular „as” w połączeniu ze zwykłym dziedziczeniem JavaScript
Zobacz więcej szczegółów tutaj http://blogs.microsoft.co.il/oric/2015/01/01/base-controller-angularjs/
Napisałem funkcję, aby to zrobić:
function extendController(baseController, extension) {
return [
'$scope', '$injector',
function($scope, $injector) {
$injector.invoke(baseController, this, { $scope: $scope });
$injector.invoke(extension, this, { $scope: $scope });
}
]
}
Możesz użyć tego w następujący sposób:
function() {
var BaseController = [
'$scope', '$http', // etc.
function($scope, $http, // etc.
$scope.myFunction = function() {
//
}
// etc.
}
];
app.controller('myController',
extendController(BaseController,
['$scope', '$filter', // etc.
function($scope, $filter /* etc. */)
$scope.myOtherFunction = function() {
//
}
// etc.
}]
)
);
}();
Plusy:
Cons:
Rozważanie rozszerzenia kontrolerów uważam za złą praktykę. Zamiast tego umieść wspólną logikę w usłudze. Rozszerzone obiekty w javascript stają się raczej skomplikowane. Jeśli chcesz użyć dziedziczenia, polecam maszynopis. Mimo to cienkie kontrolery są moim zdaniem lepszym sposobem.