Прежде всего, Инжектор , который вы получаете в конструкторе, это так называемый Инжектор слияния .
Вот его определение :
class Injector_ implements Injector {
constructor(private view: ViewData, private elDef: NodeDef|null) {}
...
}
Angular просто берет данные о просмотре и определение узла и может создавать экземпляр экземпляра Injector всякий раз, когда этого требует функция createInjector :
export function createInjector(view: ViewData, elDef: NodeDef): Injector {
return new Injector_(view, elDef);
}
Теперь вернемся кваша директива:
SomeDirective
|
deps
/ \
Injector ViewContainer
Для создания экземпляра директивы Angular разрешает зависимости через выделенную функцию resolDep
export function resolveDep(view, elDef) {
...
case ViewContainerRefTokenKey:
return asElementData(searchView, elDef.nodeIndex).viewContainer;
...
case InjectorRefTokenKey:
return createInjector(searchView, elDef);
...
}
Предположим, у вас есть такой компонент, как:
@Component({
selector: 'my-app',
template: '<h2 appSome>Hello</h2>'
})
export class AppComponent {}
В этом случае:
SomeDirective
|
deps
/ \
Injector ViewContainer
|| ||
\/ \/
resolveDep(AppComponent view, h2 elDef) resolveDep(AppComponent view, h2 elDef)
|| ||
\/ \/
createInjector viewContainerRef (AppComponent view, h2 elDef)
(created early)
||
\/
new Injector(AppComponent view, h2 elDef)
ViewContainerRef
экземпляр был создан в начале создания узла представления.Так как вам нужен узел ViewContainerRef
через DI Angular отмечают h2
со специальным флагом и таким образом он может создать экземпляр ViewContainerRef
и для сохранения этого экземпляра в данных узла h2.
if (nodeDef.flags & 16777216 /* EmbeddedViews */) {
nodeData.viewContainer = createViewContainerData(view, nodeDef, nodeData);
}
где createViewContainerData :
export function createViewContainerData(
view: ViewData, elDef: NodeDef, elData: ElementData): ViewContainerData {
return new ViewContainerRef_(view, elDef, elData);
}
Итак, что мы имеем здесь: Injector
и ViewContainer
, которые указывают на то же представление и тот же elDef.
Теперь давайтепосмотрите на ViewContainerRef definition :
class ViewContainerRef_ implements ViewContainerData {
...
constructor(private _view: ViewData, private _elDef: NodeDef, private _data: ElementData) {}
...
get injector(): Injector { return new Injector_(this._view, this._elDef); }
get parentInjector(): Injector {
let view = this._view;
let elDef = this._elDef.parent;
while (!elDef && view) {
elDef = viewParentEl(view);
view = view.parent !;
}
return view ? new Injector_(view, elDef) : new Injector_(this._view, null);
}
...
}
Case 1
injector === viewContainerRef.injector => fail
Поскольку метод getConConererRef.injector создает новый экземпляр Injector с тем жеview и elDef.
Таким образом, верно следующее:
injector.view === viewContainerRef.injector.view
injector.elDef === viewContainerRef.injector.elDef
Случай 2
injector === viewContainerRef.parentInjector => fail
Поскольку метод получения parentInjector получит новый экземпляр Injector с родительским представлением и родительскимelDef.
Родительское представление здесь - это представление хоста, а elDef - my-app.
Случай 3
viewContainerRef.injector === viewContainerRef.parentInjector => fail
Должно быть очевидно, что они не равны, поскольку указывают на другое представление и на elDef, и создаются с помощью оператора new
.
Наконец, вы можете прочитать:
Что вы всегда хотели знать о дереве инъекций угловой зависимости