Cái $scope
mà bạn thấy được đưa vào bộ điều khiển không phải là một số dịch vụ (giống như phần còn lại của nội dung có thể tiêm), mà là một đối tượng Phạm vi. Nhiều đối tượng phạm vi có thể được tạo (thường là kế thừa nguyên mẫu từ phạm vi cha). Gốc của tất cả các phạm vi là $rootScope
và bạn có thể tạo một phạm vi con mới bằng cách sử dụng $new()
phương thức của bất kỳ phạm vi nào (bao gồm cả $rootScope
).
Mục đích của Phạm vi là "kết dính" bản trình bày và logic kinh doanh của ứng dụng của bạn. Không có nhiều ý nghĩa khi chuyển $scope
một dịch vụ vào một dịch vụ.
Dịch vụ là các đối tượng đơn lẻ được sử dụng (trong số những thứ khác) để chia sẻ dữ liệu (ví dụ: giữa một số bộ điều khiển) và thường đóng gói các đoạn mã có thể sử dụng lại (vì chúng có thể được đưa vào và cung cấp "dịch vụ" của chúng trong bất kỳ phần nào của ứng dụng cần chúng: bộ điều khiển, chỉ thị, bộ lọc, các dịch vụ khác, v.v.).
Tôi chắc chắn, nhiều cách tiếp cận khác nhau sẽ phù hợp với bạn. Một là:
Vì StudentService
phụ trách xử lý dữ liệu sinh viên, bạn có thể có StudentService
một loạt các sinh viên và để nó "chia sẻ" nó với bất kỳ ai có thể quan tâm (ví dụ: của bạn $scope
). Điều này thậm chí còn có ý nghĩa hơn, nếu có các chế độ xem / bộ điều khiển / bộ lọc / dịch vụ khác cần có quyền truy cập vào thông tin đó (nếu không có bất kỳ thông tin nào ngay bây giờ, đừng ngạc nhiên nếu chúng bắt đầu xuất hiện sớm).
Mỗi khi một sinh viên mới được thêm vào (sử dụng save()
phương thức của dịch vụ ), mảng sinh viên của chính dịch vụ sẽ được cập nhật và mọi đối tượng khác chia sẻ mảng đó cũng sẽ được cập nhật tự động.
Dựa trên cách tiếp cận được mô tả ở trên, mã của bạn có thể trông giống như sau:
angular.
module('cfd', []).
factory('StudentService', ['$http', '$q', function ($http, $q) {
var path = 'data/people/students.json';
var students = [];
// In the real app, instead of just updating the students array
// (which will be probably already done from the controller)
// this method should send the student data to the server and
// wait for a response.
// This method returns a promise to emulate what would happen
// when actually communicating with the server.
var save = function (student) {
if (student.id === null) {
students.push(student);
} else {
for (var i = 0; i < students.length; i++) {
if (students[i].id === student.id) {
students[i] = student;
break;
}
}
}
return $q.resolve(student);
};
// Populate the students array with students from the server.
$http.get(path).then(function (response) {
response.data.forEach(function (student) {
students.push(student);
});
});
return {
students: students,
save: save
};
}]).
controller('someCtrl', ['$scope', 'StudentService',
function ($scope, StudentService) {
$scope.students = StudentService.students;
$scope.saveStudent = function (student) {
// Do some $scope-specific stuff...
// Do the actual saving using the StudentService.
// Once the operation is completed, the $scope's `students`
// array will be automatically updated, since it references
// the StudentService's `students` array.
StudentService.save(student).then(function () {
// Do some more $scope-specific stuff,
// e.g. show a notification.
}, function (err) {
// Handle the error.
});
};
}
]);
Một điều bạn nên cẩn thận khi sử dụng phương pháp này là không bao giờ gán lại mảng của dịch vụ, vì khi đó bất kỳ thành phần nào khác (ví dụ: phạm vi) sẽ vẫn tham chiếu đến mảng ban đầu và ứng dụng của bạn sẽ bị hỏng.
Ví dụ: xóa mảng trong StudentService
:
/* DON'T DO THAT */
var clear = function () { students = []; }
/* DO THIS INSTEAD */
var clear = function () { students.splice(0, students.length); }
Ngoài ra, hãy xem bản demo ngắn này .
CẬP NHẬT ÍT NHẤT:
Một vài từ để tránh sự nhầm lẫn có thể phát sinh khi nói về việc sử dụng một dịch vụ, nhưng không tạo ra nó với service()
chức năng.
Trích dẫn các tài liệu về$provide
:
Một dịch vụ Angular là một đối tượng singleton được tạo bởi một nhà máy dịch vụ . Các nhà máy dịch vụ này là các chức năng do một nhà cung cấp dịch vụ tạo ra . Các nhà cung cấp dịch vụ là các hàm khởi tạo. Khi được khởi tạo, chúng phải chứa một thuộc tính được gọi $get
, giữ chức năng nhà máy dịch vụ .
[...]
... $provide
dịch vụ có thêm các phương thức trợ giúp để đăng ký dịch vụ mà không cần chỉ định nhà cung cấp:
- nhà cung cấp (nhà cung cấp) - đăng ký nhà cung cấp dịch vụ với $ injection
- hằng (obj) - đăng ký một giá trị / đối tượng có thể được truy cập bởi các nhà cung cấp và dịch vụ.
- value (obj) - đăng ký một giá trị / đối tượng chỉ có thể được truy cập bởi các dịch vụ, không phải nhà cung cấp.
- factory (fn) - đăng ký một hàm nhà máy dịch vụ, fn, sẽ được bao bọc trong một đối tượng nhà cung cấp dịch vụ, có thuộc tính $ get sẽ chứa hàm nhà máy đã cho.
- service (class) - đăng ký một hàm tạo, lớp sẽ được bao bọc trong một đối tượng cung cấp dịch vụ, có thuộc tính $ get sẽ khởi tạo một đối tượng mới bằng cách sử dụng hàm khởi tạo đã cho.
Về cơ bản, những gì nó nói là mọi dịch vụ Angular đều được đăng ký bằng cách sử dụng $provide.provider()
, nhưng có các phương thức "phím tắt" cho các dịch vụ đơn giản hơn (hai trong số đó là service()
và factory()
).
Tất cả đều "tóm gọn" vào một dịch vụ, vì vậy không có gì khác biệt nhiều so với phương pháp bạn sử dụng (miễn là phương pháp đó có thể đáp ứng các yêu cầu đối với dịch vụ của bạn).
BTW, provider
vs service
vs factory
là một trong những khái niệm khó hiểu nhất đối với những người mới đến với Angular, nhưng may mắn thay, có rất nhiều tài nguyên (ở đây trên SO) để làm cho mọi thứ dễ dàng hơn. (Chỉ cần tìm kiếm xung quanh.)
(Tôi hy vọng điều đó sẽ rõ ràng - hãy cho tôi biết nếu không.)