我有点困惑,为什么ngAfterContentInit在这种情况下执行两次。我创建了一个简化版本的应用程序来重现错误。简而言之,我使用*contentItem
来标记组件,然后由standard-layout
组件进行渲染。只要我遵循这种模式,demo
的ngAfterContentInit
被执行两次。停止ngAfterContentInit执行两次
我放在GitHub上的演示应用程序,这将重现错误: https://github.com/jVaaS/stackoverflow/tree/master/ngaftercontentinit
否则这里是重要的位:
车-app.dart:
@Component(
selector: "buggy-app",
template: """
<standard-layout>
<demo *contentItem></demo>
</standard-layout>
""",
directives: const [
ContentItemDirective,
StandardLayout,
Demo
]
)
class BuggyApp implements AfterContentInit {
@override
ngAfterContentInit() {
print(">>> ngAfterContentInit: BuggyApp");
}
}
标准布局.dart:
////////////////////////////////////////////////////////////////////////////////
///
/// Standard Layout Component
/// <standard-layout></standard-layout>
///
@Component(
selector: "standard-layout",
template: """
<div *ngFor="let item of contentItems ?? []">
<template [ngTemplateOutlet]="item.template"></template>
</div>
""",
directives: const [ROUTER_DIRECTIVES, ContentItem])
class StandardLayout implements AfterContentInit {
@ContentChildren(ContentItemDirective)
QueryList<ContentItemDirective> contentItems;
@override
ngAfterContentInit() {
print(">>> ngAfterContentInit: StandardLayout");
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// Content Item Directive
/// *contentItem
///
@Directive(selector: '[contentItem]')
class ContentItemDirective implements AfterContentInit {
final ViewContainerRef vcRef;
final TemplateRef template;
final ComponentResolver componentResolver;
ContentItemDirective(this.vcRef, this.template, this.componentResolver);
ComponentRef componentRef;
@override
ngAfterContentInit() async {
final componentFactory =
await componentResolver.resolveComponent(ContentItem);
componentRef = vcRef.createComponent(componentFactory);
(componentRef.instance as ContentItem)
..template = template;
}
}
////////////////////////////////////////////////////////////////////////////////
///
/// Content Item Generator
///
@Component(
selector: "content-item",
host: const {
'[class.content-item]': "true",
},
template: """
<template [ngTemplateOutlet]="template"></template>
""",
directives: const [NgTemplateOutlet]
)
class ContentItem {
TemplateRef template;
}
////////////////////////////////////////////////////////////////////////////////
和最后demo.dart
:
@Component(
selector: "demo",
template: "Hello World Once, but demo prints twice!")
class Demo implements AfterContentInit {
@override
ngAfterContentInit() {
print(">>> ngAfterContentInit: Demo");
}
}
main.dart
没有太多的变量:
void main() {
bootstrap(BuggyApp);
}
但在终端看时:
所以demo
组件只呈现一次,但其ngAfterContentInit
正在执行两次,当您的假设是它只被执行一次时会造成严重破坏。
我已经尝试添加哈克解决方法,但似乎组件实际上得到重新呈现两次:
int counter = 0;
@override
ngAfterContentInit() {
if (counter == 0) {
print(">>> ngAfterContentInit: Demo");
counter++;
}
}
这是一个错误的角度或者是有什么我可以做,以避免这种情况?
pubspec.yaml
的情况下,它的需要:
name: bugdemo
version: 0.0.0
description: Bug Demo
environment:
sdk: '>=1.13.0 <2.0.0'
dependencies:
angular2: 3.1.0
browser: ^0.10.0
http: any
js: ^0.6.0
dart_to_js_script_rewriter: ^1.0.1
transformers:
- angular2:
platform_directives:
- package:angular2/common.dart#COMMON_DIRECTIVES
platform_pipes:
- package:angular2/common.dart#COMMON_PIPES
entry_points: web/main.dart
- dart_to_js_script_rewriter
- $dart2js:
commandLineOptions: [--enable-experimental-mirrors]
和index.html
好措施:
<!DOCTYPE html>
<html>
<head>
<title>Strange Bug</title>
</head>
<body>
<buggy-app>
Loading ...
</buggy-app>
<script async src="main.dart" type="application/dart"></script>
<script async src="packages/browser/dart.js"></script>
</body>
</html>
更新
于是有人认为,可能是因为它只会发生两次在开发模式。我已经完成了pub build
并运行了index.html
,它现在在常规Chrome中包含main.dart.js
。
它仍然执行两次,试图用ngAfterViewInit
而那也是执行两次。
登录在此期间的错误: https://github.com/dart-lang/angular/issues/478
如果您使用'ngFor'为子组件迭代,则不能将被调用的'ngAfterInit()'限制为一个确定的限制。 – Aravind
好的,能够呈现多个受限制的子组件并且只获得一个'ngAfterContentInit'调用的解决方法是什么? –
你想达到什么目的。我很困惑。请详细说明 – Aravind