我有點困惑,爲什麼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