gpt4 book ai didi

angular - ViewChild 和 ContentChild 的所有有效选择器是什么?

转载 作者:太空狗 更新时间:2023-10-29 16:51:23 26 4
gpt4 key购买 nike

我正在寻找可用于通过 @ViewChild@ContentChild 访问子组件/DOM 元素的有效选择器的完整列表。

假设我有一个 child HelloComponent:

我知道我可以添加一个模板 #ref 并查询它,就像这样:

<hello #myHello></hello>

@ViewChild('myHello') myHello: HelloComponent;

或者我可以直接查找该组件(没有模板 #ref):

@ViewChild(HelloComponent) myHello: HelloComponent;

this issue ,有人提到可以使用以下选择器:

we are currently supporting a sub-set of CSS selectors:
* element selectors
* attribute selectors (including values)
* :not(...) pseudo-selector
* combination of the above (including ,)

但是当我在 Stackblitz 中测试这些以验证 (here's the link to that) 时,我实际上无法让前三个中的任何一个工作。 (检查控制台以查看 undefined 我无法工作的选择器类型。我不确定我是否对这些选择器做错了什么或者实际列表是否不同.)

那么,哪些选择器会起作用呢?此外,@ViewChild@ContentChild@ViewChildren@ContentChildren 的列表是否相同?

最佳答案

首先,正如@JB Nizet 已经在评论中提到的 the comment in the issue是错误的:它与查询选择器无关,而是指 directive selector .

让我们来看看我们可以使用哪种选择器进行查询。

Angular 文档 states用于查询:

selector - the directive type or the name used for querying.

指令类型

似乎任何人都应该清楚(1) 我们可以查询由@Component@Directive 装饰器装饰的任何类

@Component({
selector: 'some-comp',
template: '...'
})
export class SomeComp {}

@Directive({
selector: '[someDir]'
})
export class SomeDir {}

@Component({
selector: 'host-comp',
template: `
<some-comp someDir></some-comp>
`
})
export class HostComp {
@ViewChild(SomeComp) someComp: SomeComp;
@ViewChild(SomeDir) someDir: SomeDir;
}

用于查询的名称

对我来说,这是令人困惑的描述。

原来这里的名字是(2)template reference variable的名字这是一个字符串:

@Component({
selector: 'host-comp',
template: `
<some-comp #someComp></some-comp>
`
})
export class HostComp {
@ViewChild('someComp') someComp: SomeComp;
}

我们可以到这里结束,但现在是查看 Angular 源代码并深入研究的时候了。

隐藏行为

让我们看看the code Angular 编译器用来读取查询元数据:

private _queryVarBindings(selector: any): string[] { return selector.split(/\s*,\s*/); }

private _getQueryMetadata(q: Query, propertyName: string, typeOrFunc: Type|Function):
cpl.CompileQueryMetadata {
let selectors: cpl.CompileTokenMetadata[];
if (typeof q.selector === 'string') {
selectors =
this._queryVarBindings(q.selector).map(varName => this._getTokenMetadata(varName));
} else {
if (!q.selector) {
this._reportError(
syntaxError(
`Can't construct a query for the property ...`),
typeOrFunc);
selectors = [];
} else {
selectors = [this._getTokenMetadata(q.selector)];
}
}

从上面的代码我们可以得出结论:

让我们应用从上面的代码中学到的知识。

我们(3) 可以通过使用除以,的几个模板引用变量来查询多个值:

@Component({
selector: 'a',
template: '...'
})
export class A {}

@Component({
selector: 'b',
template: '...'
})
export class B {}

@Component({
selector: 'host-comp',
template: `
<a #a></a>
<b #b></b>
`
})
export class HostComp {
@ViewChildren('a, b') components;

ngAfterViewInit() {
console.log(this.components); // [A, B]
}
}

(4) 可以查询在组件或指令上定义的提供程序。(另请参阅@Ilia Volk 添加的示例)

@Component({
selector: 'a',
template: '...',
providers: [SomeService]
})
export class A {}

@Component({
selector: 'host-comp',
template: `<a></a>`
})
export class HostComp {
@ViewChild(SomeService) someService: SomeService;
}

由于字符串可以作为提供者的标记,我们可以(5) 查询通过字符串标记定义的多个提供者

@Component({
selector: 'a',
providers: [{ provide: 'tokenA', useValue: 'TokenAValue' }],
template: '...'
})
export class A { }

@Component({
selector: 'b',
providers: [{ provide: 'tokenB', useValue: 'TokenBValue' }],
template: '...'
})
export class B { }

@Component({
selector: 'host-comp',
template: `
<a #a></a>
<b #b></b>
`
})
export class HostComp {
@ViewChildren('tokenA, tokenB') stringTokenProviders;

ngAfterViewInit() {
console.log(this.stringTokenProviders); // ['TokenAValue', 'TokenBValue']
}
}

我们的下一站是核心包中的位置 angular returns us the value of particular query :

export function getQueryValue(
view: ViewData, nodeDef: NodeDef, queryValueType: QueryValueType): any {
if (queryValueType != null) {
// a match
switch (queryValueType) {
case QueryValueType.RenderElement:
return asElementData(view, nodeDef.nodeIndex).renderElement;
case QueryValueType.ElementRef:
return new ElementRef(asElementData(view, nodeDef.nodeIndex).renderElement);
case QueryValueType.TemplateRef:
return asElementData(view, nodeDef.nodeIndex).template;
case QueryValueType.ViewContainerRef:
return asElementData(view, nodeDef.nodeIndex).viewContainer;
case QueryValueType.Provider:
return asProviderData(view, nodeDef.nodeIndex).instance;
}
}
}
上面代码中的

RenderElement 是一些我们无法查询的内部标记。

ElementRef 可以通过模板引用变量或使用 read option 查询

(6) TemplateRef可以通过selector查询:

@Component({
selector: 'host-comp',
template: `
<ng-template></ng-template>
`
})
export class HostComp {
@ViewChild(TemplateRef) template;
}

当然还有 ViewContainerRef 通过 read 选项。

Provider 可以通过使用 read 选项或通过选择器获得,正如我在这个答案中间所描述的那样。

关于angular - ViewChild 和 ContentChild 的所有有效选择器是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49162473/

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