Tôi có ba bộ điều khiển khá giống nhau. Tôi muốn có một bộ điều khiển mà ba cái này mở rộng và chia sẻ các chức năng của nó.
Tôi có ba bộ điều khiển khá giống nhau. Tôi muốn có một bộ điều khiển mà ba cái này mở rộng và chia sẻ các chức năng của nó.
Câu trả lời:
Có lẽ bạn không mở rộng bộ điều khiển nhưng có thể mở rộng bộ điều khiển hoặc biến một bộ điều khiển thành một hỗn hợp gồm nhiều bộ điều khiển.
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.
}]);
Khi bộ điều khiển chính được tạo, logic chứa trong nó cũng được thực thi. Xem $ control () để biết thêm thông tin về nhưng chỉ $scope
giá trị cần được thông qua. Tất cả các giá trị khác sẽ được tiêm bình thường.
@mwarren , mối quan tâm của bạn được chăm sóc tự động một cách kỳ diệu bằng cách tiêm phụ thuộc Angular. Tất cả những gì bạn cần là tiêm $ scope, mặc dù bạn có thể ghi đè các giá trị được tiêm khác nếu muốn. Lấy ví dụ sau:
(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>
Mặc dù $ document không được truyền vào 'SimpleContoder' khi nó được tạo bởi 'documentContoder' $ document được chèn cho chúng ta.
$.extend()
, bạn chỉ cần gọi$controller('CtrlImpl', {$scope: $scope});
angular.extend
(hoặc $.extend
) thực sự có nghĩa là chỉ mở rộng $scope
, nhưng nếu bộ điều khiển cơ sở của bạn cũng xác định một số thuộc tính (ví dụ this.myVar=5
), bạn chỉ có quyền truy cập this.myVar
vào bộ điều khiển mở rộng khi sử dụngangular.extend
handleSubmitClick
cái handleLogin
mà lần lượt sẽ có một loginSuccess
và loginFail
. Vì vậy, trong điều khiển mở rộng của tôi, tôi sau đó đã phải quá tải handleSubmitClick
, handleLogin
và loginSucess
cho đúng loginSuccess
chức năng được sử dụng.
Để kế thừa, bạn có thể sử dụng các mẫu thừa kế JavaScript tiêu chuẩn. Đây là một bản demo sử dụng$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);
Trong trường hợp bạn sử dụng controllerAs
cú pháp (mà tôi rất khuyến khích), việc sử dụng mẫu kế thừa cổ điển thậm chí còn dễ dàng hơn:
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);
Một cách khác có thể là chỉ tạo hàm xây dựng "trừu tượng" sẽ là bộ điều khiển cơ sở của bạn:
function BaseController() {
this.click = function () {
//some actions here
};
}
module.controller('ChildCtrl', ['$scope', function ($scope) {
BaseController.call($scope);
$scope.anotherClick = function () {
//other actions
};
}]);
Chà, tôi không chắc chắn chính xác những gì bạn muốn đạt được, nhưng thường thì Dịch vụ là con đường để đi. Bạn cũng có thể sử dụng các đặc điểm kế thừa Phạm vi của Angular để chia sẻ mã giữa các bộ điều khiển:
<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( )
là một cách sạch sẽ hơn nhiều để làm điều đó, vì đó là nơi nó thực sự được xác định?
Bạn không mở rộng bộ điều khiển. Nếu chúng thực hiện các chức năng cơ bản giống nhau thì các chức năng đó cần được chuyển sang một dịch vụ. Dịch vụ đó có thể được đưa vào bộ điều khiển của bạn.
Một giải pháp tốt khác được lấy từ bài viết này :
// 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;
});
}]);
Bạn có thể tạo một dịch vụ và kế thừa hành vi của nó trong bất kỳ bộ điều khiển nào chỉ bằng cách tiêm nó.
app.service("reusableCode", function() {
var reusableCode = {};
reusableCode.commonMethod = function() {
alert('Hello, World!');
};
return reusableCode;
});
Sau đó, trong bộ điều khiển của bạn mà bạn muốn mở rộng từ dịch vụ tái sử dụng ở trên:
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
Bạn có thể thử một cái gì đó như thế này (chưa được thử nghiệm):
function baseController(callback){
return function($scope){
$scope.baseMethod = function(){
console.log('base method');
}
callback.apply(this, arguments);
}
}
app.controller('childController', baseController(function(){
}));
Bạn có thể gia hạn với một dịch vụ , nhà máy hoặc nhà cung cấp . chúng giống nhau nhưng với mức độ linh hoạt khác nhau.
đây là một ví dụ sử dụng nhà máy: 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
});
Và ở đây bạn cũng có thể sử dụng chức năng lưu trữ:
<div ng-controller="myController">
<input ng-blur="myFactory.store()" />
</div>
Bạn có thể trực tiếp sử dụng bộ điều khiển $ ('ParentContoder', {$ scope: $ scope}) Ví dụ
module.controller('Parent', ['$scope', function ($scope) {
//code
}])
module.controller('CtrlImplAdvanced', ['$scope', '$controller', function ($scope, $controller) {
//extend parent controller
$controller('CtrlImpl', {$scope: $scope});
}]);
Bạn có thể sử dụng cú pháp "như" Angular kết hợp với kế thừa JavaScript đơn giản
Xem thêm chi tiết tại đây http://bloss.microsoft.co.il/oric/2015/01/01/base-controll-angularjs/
Tôi đã viết một chức năng để làm điều này:
function extendController(baseController, extension) {
return [
'$scope', '$injector',
function($scope, $injector) {
$injector.invoke(baseController, this, { $scope: $scope });
$injector.invoke(extension, this, { $scope: $scope });
}
]
}
Bạn có thể sử dụng nó như thế này:
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.
}]
)
);
}();
Ưu điểm:
Nhược điểm:
Tôi coi việc mở rộng bộ điều khiển là thực hành xấu. Thay vì đưa logic chia sẻ của bạn vào một dịch vụ. Các đối tượng mở rộng trong javascript có xu hướng trở nên khá phức tạp. Nếu bạn muốn sử dụng kế thừa, tôi muốn giới thiệu bản thảo. Tuy nhiên, bộ điều khiển mỏng là cách tốt hơn để đi theo quan điểm của tôi.