$scope
あなたは、コントローラの中に注入されている参照しているが(注射用のものの残りの部分のような)一部のサービスではなく、スコープのオブジェクトです。多くのスコープオブジェクトを作成できます(通常は親スコープから継承します)。すべてのスコープのルートはで$rootScope
あり$new()
、任意のスコープ(を含む$rootScope
)のメソッドを使用して新しい子スコープを作成できます。
スコープの目的は、アプリのプレゼンテーションとビジネスロジックを「接着」することです。を$scope
サービスに渡すことはあまり意味がありません。
サービスは、(とりわけ)データを共有するために(特にいくつかのコントローラー間で)使用されるシングルトンオブジェクトであり、再利用可能なコードの一部をカプセル化します(それらを挿入して、それらを必要とするアプリの任意の部分で「サービス」を提供できるため:ディレクティブ、フィルター、その他のサービスなど)。
きっと、いろいろなアプローチがうまくいくと思います。一つはこれです:
ので、StudentService
生徒データを扱う担当している、あなたが持つことができStudentService
、学生の配列を維持し、興味があるかもしれません誰と一緒に「シェア」それを聞かせて(例えば、あなたが$scope
)。その情報にアクセスする必要のある他のビュー/コントローラー/フィルター/サービスがある場合、これはさらに理にかなっています(すぐに表示されない場合でも、すぐにポップアップし始めても驚かないでください)。
(サービスのsave()
メソッドを使用して)新しい生徒が追加されるたびに、サービスの独自の生徒の配列が更新され、その配列を共有する他のすべてのオブジェクトも自動的に更新されます。
上記のアプローチに基づくと、コードは次のようになります。
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.
});
};
}
]);
このアプローチを使用する際に注意する必要があるのは、サービスの配列を再割り当てしないことです。これにより、他のコンポーネント(スコープなど)が元の配列を参照し続け、アプリが破損します。
たとえば、配列をクリアするにはStudentService
:
/* DON'T DO THAT */
var clear = function () { students = []; }
/* DO THIS INSTEAD */
var clear = function () { students.splice(0, students.length); }
また、この短いデモもご覧ください。
少し更新:
サービスの使用について話しているときに発生する可能性がある混乱を避けるためのいくつかの単語service()
。
上$provide
のドキュメントを引用:
Angular サービスは、サービスファクトリによって作成されたシングルトンオブジェクトです。これらのサービスファクトリは、サービスプロバイダによって作成された機能です。サービスプロバイダは、コンストラクタ関数です。インスタンス化されたとき$get
は、サービスファクトリ関数を保持するというプロパティが含まれている必要があります。
[...]
... $provide
サービスには、プロバイダーを指定せずにサービスを登録するための追加のヘルパーメソッドがあります。
- provider(provider) -$ injectorでサービスプロバイダーを登録します
- constant(obj) -プロバイダーとサービスがアクセスできる値/オブジェクトを登録します。
- value(obj) -プロバイダーではなく、サービスのみがアクセスできる値/オブジェクトを登録します。
- factory(fn) -サービスプロバイダーオブジェクトにラップされるサービスファクトリ関数fnを登録します。このオブジェクトの$ getプロパティには、指定されたファクトリ関数が含まれます。
- service(class) -サービスプロバイダーオブジェクトでラップされるコンストラクター関数を登録します。$ getプロパティは、指定されたコンストラクター関数を使用して新しいオブジェクトをインスタンス化します。
基本的に、すべてのAngularサービスはを使用して登録され$provide.provider()
ますが、より単純なサービスには「ショートカット」メソッドがあります(そのうちの2つはservice()
およびfactory()
)。
すべてがサービスに「集約」されるため、どのメソッドを使用してもそれほど大きな違いはありません(サービスの要件がそのメソッドでカバーできる限り)。
ところで、provider
vs service
vs factory
はAngularの初心者にとって最もわかりにくい概念の1つですが、幸いなことに、物事を簡単にするためのリソース(ここではSO)がたくさんあります。(検索してみてください。)
(それがクリアされることを願っています-クリアされない場合はお知らせください。)