Замість того, щоб просто заповнити таблицю словами "так" і "ні" без жодних пояснень, я піду трохи детальніше.
[Зауважте, додано після закінчення: це в кінцевому підсумку було ... трохи довше, ніж я очікував. Внизу є tl; dr, але я сподіваюся, що це буде інформаційно.]
[Ця відповідь також була додана у вікі AngularJS: Розуміння ін'єкції залежності ]
$provide
Служба відповідає за розповідь ANGULAR , як створювати нові ін'єкційні речі; ці речі називаються послугами . Служби визначаються речами, які називаються постачальниками. Це те, що ви створюєте під час використання $provide
. Визначення постачальника здійснюється за допомогою provider
методу на $provide
сервісі, і ви можете отримати його $provide
, попросивши ввести його у функцію програми config
. Прикладом може бути щось подібне:
app.config(function($provide) {
$provide.provider('greeting', function() {
this.$get = function() {
return function(name) {
alert("Hello, " + name);
};
};
});
});
Тут ми визначили нового постачальника послуги під назвою greeting
; ми можемо ввести змінну, названу greeting
в будь-яку функцію ін'єкцій (наприклад, контролери, докладніше про це пізніше), і Angular зателефонує до $get
функції постачальника, щоб повернути новий екземпляр послуги. У цьому випадку річ, яка буде введена, - це функція, яка приймає name
параметр і alert
повідомлення sa, засноване на імені. Ми можемо використовувати його так:
app.controller('MainController', function($scope, greeting) {
$scope.onClick = function() {
greeting('Ford Prefect');
};
});
Тепер ось хитрість. factory
,, service
і value
все це лише ярлики для визначення різних частин провайдера - тобто вони надають засоби визначення постачальника без необхідності вводити всі ці речі. Наприклад, ви можете написати того самого постачальника саме так:
app.config(function($provide) {
$provide.factory('greeting', function() {
return function(name) {
alert("Hello, " + name);
};
});
});
Це важливо зрозуміти, тому я перефразую: під кришкою AngularJS називає той самий код, який ми написали вище ( $provide.provider
версія) для нас. Існує буквально, на 100% різниці у двох версіях. value
працює так само - якщо все, що ми повернемося з нашої $get
функції (він же - наша factory
функція) - завжди однаковий, ми можемо записати ще менше коду, використовуючи value
. Наприклад, оскільки ми завжди повертаємо ту саму функцію для нашого greeting
сервісу, ми можемо використовувати її і value
для визначення:
app.config(function($provide) {
$provide.value('greeting', function(name) {
alert("Hello, " + name);
});
});
Знову ж таки, це на 100% ідентично двом іншим методам, які ми використовували для визначення цієї функції - це лише спосіб зберегти певний текст.
Тепер ви, мабуть, помітили цю дратівливу app.config(function($provide) { ... })
річ, яку я використовував. Оскільки визначення нових провайдерів (за допомогою будь-якого з наведених вище методів) є настільки поширеним, AngularJS розкриває $provider
методи безпосередньо на об'єкті модуля, щоб зберегти ще більше введення тексту:
var myMod = angular.module('myModule', []);
myMod.provider("greeting", ...);
myMod.factory("greeting", ...);
myMod.value("greeting", ...);
Усі вони роблять те саме, що і більш докладні app.config(...)
версії, які ми використовували раніше.
Один ін'єкційний, який я поки пропустив, це constant
. Поки що досить просто сказати, що це працює так само value
. Ми побачимо, що є одна різниця пізніше.
Для огляду , все ці фрагменти коду роблять точно те ж саме:
myMod.provider('greeting', function() {
this.$get = function() {
return function(name) {
alert("Hello, " + name);
};
};
});
myMod.factory('greeting', function() {
return function(name) {
alert("Hello, " + name);
};
});
myMod.value('greeting', function(name) {
alert("Hello, " + name);
});
Інжектор відповідає за фактичне створення примірників наших служб за допомогою коду, який ми надали за допомогою $provide
(не призначено каламбуру). Щоразу, коли ви пишете функцію, яка приймає введені аргументи, ви бачите інжектор на роботі. Кожна програма AngularJS має сингл, $injector
який створюється при першому запуску програми; Ви можете його вхопити, $injector
ввівши будь-яку ін'єкційну функцію (так, $injector
знає, як себе вводити!)
Після цього $injector
ви можете отримати екземпляр певної послуги, зателефонувавши get
до неї з назвою служби. Наприклад,
var greeting = $injector.get('greeting');
greeting('Ford Prefect');
Інжектор також відповідає за введення послуг у функції; наприклад, ви можете магічним чином вводити послуги в будь-яку функцію, що використовується, використовуючи invoke
метод інжектора ;
var myFunction = function(greeting) {
greeting('Ford Prefect');
};
$injector.invoke(myFunction);
Варто зазначити, що інжектор створить екземпляр послуги лише один раз . Потім він кешує те, що постачальник повертає за назвою послуги; наступного разу, коли ви попросите послугу, ви фактично отримаєте такий самий об’єкт.
Отже, щоб відповісти на ваше запитання, ви можете ввести послуги в будь-яку функцію, яка викликається$injector.invoke
. Це включає
- функції визначення контролера
- функції визначення директиви
- функції визначення фільтра
- що
$get
методи провайдерів (інакше factory
функція визначення)
Оскільки constant
s і value
s завжди повертають статичне значення, вони не викликаються через інжектор, і тому ви нічого не можете вводити їм.
Налаштування постачальників
Ви можете бути здивовані , чому хтось -то буде турбувати , щоб створити повноцінний провайдер з provide
методом , якщо factory
, value
і т.д. так набагато простіше. Відповідь полягає в тому, що провайдери дозволяють багато конфігурації. Ми вже згадували, що коли ви створюєте послугу через постачальника (або будь-який із ярликів, який надає Angular), ви створюєте нового постачальника, який визначає, як будується ця послуга. Що я не згадував, це те, що ці постачальники можуть вводитись у config
розділи вашої програми, щоб ви могли з ними взаємодіяти!
По-перше, Angular запускає вашу програму у дві фази - config
та run
фази. Як config
ми вже бачили, фаза - це те, де ви можете налаштувати будь-яких постачальників послуг за потребою. Тут також встановлюються директиви, контролери, фільтри тощо. run
Фаза, як ви можете здогадатися, де Кутова фактично компілює DOM і запускає додаток.
Ви можете додати додатковий код, який потрібно запустити в цих фазах, за допомогою функцій myMod.config
і myMod.run
- кожен приймає функцію, яку потрібно запустити протягом цієї конкретної фази. Як ми побачили в першому розділі, ці функції є ін'єкційними - ми ввели вбудований $provide
сервіс у нашому першому зразку коду. Однак, що варто зауважити, це те, що під час config
фази можна вводити тільки постачальників послуг (за винятком служб у AUTO
модулі-- $provide
та $injector
).
Наприклад, не дозволяється :
myMod.config(function(greeting) {
// WON'T WORK -- greeting is an *instance* of a service.
// Only providers for services can be injected in config blocks.
});
Те , що ви робите мати доступ до будь-яких постачальникам за послуги , які ви зробили:
myMod.config(function(greetingProvider) {
// a-ok!
});
Є один важливий виняток: constant
s, оскільки вони не можуть бути змінені, дозволено вводити всередину config
блоків (таким чином вони відрізняються від value
s). Доступ до них здійснюється лише одним іменем ( Provider
суфікс не потрібен).
Щоразу, коли ви визначили постачальника послуги, цей постачальник отримує ім'я serviceProvider
, де service
ім'я послуги. Тепер ми можемо використовувати владу провайдерів і робити якісь складніші речі!
myMod.provider('greeting', function() {
var text = 'Hello, ';
this.setText = function(value) {
text = value;
};
this.$get = function() {
return function(name) {
alert(text + name);
};
};
});
myMod.config(function(greetingProvider) {
greetingProvider.setText("Howdy there, ");
});
myMod.run(function(greeting) {
greeting('Ford Prefect');
});
Тепер у нашого постачальника функція називається, setText
яку ми можемо використовувати для налаштування свого alert
; ми можемо отримати доступ до цього провайдера в config
блоці, щоб викликати цей метод і налаштувати послугу. Коли ми нарешті запустимо наш додаток, ми можемо взяти greeting
послугу та спробувати її, щоб переконатися, що наше налаштування набуло чинності.
Оскільки це складніший приклад, ось робоча демонстрація: http://jsfiddle.net/BinaryMuse/9GjYg/
Функції контролера можна вводити, але самі контролери не можна вводити в інші речі. Це тому, що контролери не створюються через провайдера. Натомість існує вбудована послуга Angular, $controller
яка відповідає за налаштування контролерів. Коли ви телефонуєте myMod.controller(...)
, ви фактично звертаєтесь до цього постачальника послуг , як і в останньому розділі.
Наприклад, коли ви визначаєте такий контролер:
myMod.controller('MainController', function($scope) {
// ...
});
Що ви насправді робите:
myMod.config(function($controllerProvider) {
$controllerProvider.register('MainController', function($scope) {
// ...
});
});
Пізніше, коли Angular потрібно створити екземпляр свого контролера, він використовує $controller
сервіс (який, у свою чергу, використовує $injector
для виклику функції вашого контролера, щоб він також вводив свої залежності).
Фільтри та директиви
filter
і directive
працювати точно так само, як controller
; filter
використовує послугу, яку називають $filter
та її постачальник $filterProvider
, тоді як directive
використовує послугу, яку називають $compile
та її постачальник $compileProvider
. Деякі посилання:
Відповідно до інших прикладів, myMod.filter
і myMod.directive
це ярлики для налаштування цих служб.
Отже, підводячи підсумок, будь-яка функція, яку $injector.invoke
можна викликати, може бути введена в неї . Сюди входить ваша діаграма (але не обмежується ними):
- контролер
- директива
- фабрика
- фільтр
- постачальник
$get
(при визначенні постачальника як об’єкта)
- функція провайдера (при визначенні провайдера як функції конструктора)
- сервіс
Провайдер створює нові послуги, які можна вводити в речі . Це включає:
- постійний
- фабрика
- постачальник
- сервіс
- значення
Однак, вбудовані сервіси на кшталт $controller
і $filter
можуть бути введені ін'єкцією, і ви можете скористатися цією службою, щоб отримати нові фільтри та контролери, які ви визначили за допомогою цих методів (навіть якщо те, що ви визначили, самі по собі не можуть бути вводиться в речі).
Окрім цього, будь-яку функцію, що викликається інжектором, можна вводити будь-яку послугу, що надається постачальником - немає ніяких обмежень (крім перелічених тут config
і run
відмінностей).