gpt4 book ai didi

angular - 注入(inject)器与 ViewContainerRef.injector 与 ViewContainerRef.parentInjector

转载 作者:行者123 更新时间:2023-12-02 00:33:26 28 4
gpt4 key购买 nike

假设我们有以下内容:

@Directive({ selector: "[appSome]" })
export class SomeDirective {
public constructor(
private viewContainerRef: ViewContainerRef,
private injector: Injector,
) {
console.log(`injector === viewContainerRef.injector: ${injector === viewContainerRef.injector}`);
console.log(`injector === viewContainerRef.parentInjector: ${injector === viewContainerRef.parentInjector}`);
console.log(`viewContainerRef.injector === viewContainerRef.parentInjector: ${viewContainerRef.injector === viewContainerRef.parentInjector}`);
}
}

这 3 种注入(inject)器有什么区别?

  1. this.injector
  2. this.viewContainerRef.injector
  3. this.viewContainerRef.parentInjector

在上面的测试中,它们都是不同的实例。

最佳答案

首先,您在构造函数中获得的Injector 是所谓的Merge Injector。 .

这是definition :

class Injector_ implements Injector {
constructor(private view: ViewData, private elDef: NodeDef|null) {}
...
}

Angular 只获取 View 数据和节点定义,并且可以在需要时通过 createInjector 实例化 Injector 实例。功能:

export function createInjector(view: ViewData, elDef: NodeDef): Injector {
return new Injector_(view, elDef);
}

现在让我们回到您的指令:

                                 SomeDirective 
|
deps
/ \
Injector ViewContainer

要创建指令实例,Angular 通过专用函数解决依赖关系 resolveDep

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 实例是在 View 节点创建的早期创建的。由于您需要 ViewContainerRef 通过 DI Angular 标记带有特殊标志的 h2 节点,这样它就可以实例化 ViewContainerRefstore 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);
}

所以我们这里有:InjectorViewContainer 指向相同的 View 和相同的 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);
}
...
}

案例一

injector === viewContainerRef.injector  => fail

因为 viewContainerRef.injector getter 创建了具有相同 View 和 elDef 的 Injector 的新实例

所以以下是正确的:

injector.view === viewContainerRef.injector.view
injector.elDef === viewContainerRef.injector.elDef

案例2

injector === viewContainerRef.parentInjector => fail

因为 parentInjector getter 将获得具有父 View 和父 elDef 的 Injector 的新实例。

这里的父 View 是主机 View ,elDef 是我的应用程序。

案例3

viewContainerRef.injector === viewContainerRef.parentInjector  => fail

应该很明显,它们不相等,因为它们也指向不同的 View 和 elDef,并且是通过 new 运算符创建的。


最后,你可以阅读:

What you always wanted to know about Angular Dependency Injection tree

关于angular - 注入(inject)器与 ViewContainerRef.injector 与 ViewContainerRef.parentInjector,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50823918/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com