- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我对为什么 ngAfterContentInit 在这种情况下执行两次感到有点困惑。我创建了一个精简版的应用程序来重现该错误。简而言之,我使用 *contentItem
来标记组件,然后由 standard-layout
组件选取这些组件进行渲染。只要我遵循这个模式,demo
的 ngAfterContentInit
就会执行两次。
我将演示应用程序放在 github 上,它将重现错误: https://github.com/jVaaS/stackoverflow/tree/master/ngaftercontentinit
否则这里是重要的部分:
buggy-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
被执行了两次,当您假设它只执行一次时,这会造成严重破坏。
我已经尝试添加一个 hacky 解决方法,但似乎组件实际上被重新渲染了两次:
int counter = 0;
@override
ngAfterContentInit() {
if (counter == 0) {
print(">>> ngAfterContentInit: Demo");
counter++;
}
}
这是 Angular 中的错误还是我可以做些什么来防止这种情况发生?
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
并在常规 Chrome 中运行了 index.html
,它现在包含 main.dart.js
。
它仍然执行了两次,尝试使用 ngAfterViewInit
并且它也执行了两次。
最佳答案
这看起来不像是一个错误。
这是为 demo.dart
生成的代码: https://gist.github.com/matanlurey/f311d90053e36cc09c6e28f28ab2d4cd
void detectChangesInternal() {
bool firstCheck = identical(this.cdState, ChangeDetectorState.NeverChecked);
final _ctx = ctx;
if (!import8.AppViewUtils.throwOnChanges) {
dbg(0, 0, 0);
if (firstCheck) {
_Demo_0_2.ngAfterContentInit();
}
}
_compView_0.detectChanges();
}
我很怀疑,所以我更改了您的打印消息以包含 hashCode
:
@override
ngAfterContentInit() {
print(">>> ngAfterContentInit: Demo $hashCode");
}
然后我看到了以下内容:
ngAfterContentInit: Demo 516575718
ngAfterContentInit: Demo 57032191
这意味着演示的两个不同实例是活的,而不仅仅是一个发射两次。然后我将 StackTrace.current
添加到 demo 的构造函数中以获取堆栈跟踪:
Demo() {
print('Created $this:$hashCode');
print(StackTrace.current);
}
得到:
0 Demo.Demo (package:bugdemo/demo.dart:11:20) 1 ViewBuggyApp1.build (package:bugdemo/buggy-app.template.dart:136:21) 2 AppView.create (package:angular2/src/core/linker/app_view.dart:180:12) 3 DebugAppView.create (package:angular2/src/debug/debug_app_view.dart:73:26) 4 TemplateRef.createEmbeddedView (package:angular2/src/core/linker/template_ref.dart:27:10) 5 ViewContainer.createEmbeddedView (package:angular2/src/core/linker/view_container.dart:86:43)
反过来说您的组件是由 BuggyApp 的模板创建的:
<standard-layout>
<demo *contentItem></demo>
</standard-layout>
更近了。继续挖掘。
我注释掉了 ContentItemDirective
,然后看到 Demo 现在创建了一次。我想您认为由于 *contentItem
而根本不会创建它,因此继续挖掘 - 并最终弄明白了。
您的 StandardLayout
组件创建模板:
<div *ngFor="let item of contentItems ?? []">
<template [ngTemplateOutlet]="item.template"></template>
</div>
但是您的 ContentItemDirective
通过 ComponentResolver 也是如此。我想你不是故意的。因此,我会弄清楚您正在尝试做什么,并通过删除在这些位置之一创建组件来解决您的问题。
关于angular - 停止 ngAfterContentInit 执行两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44832253/
我正在使用 Tkinter 在 python 上写一个小游戏(顺便说一下,我不允许使用任何其他非内置模块)并且我想在主窗口上播放背景歌曲,这是那个包含标题,以及转到其他窗口和内容的按钮... 所以问题
我有一个 Azure WebJob,它在一个非常简单的应用服务标准:1 Small(计划)上运行。 现在,我的 WebJob(有 5 个函数正在运行)出现问题 - 我想停止 5 个正在运行的函数中的
我在 MacOS Lion 上使用 XCode 4.2。在模拟器中调试 iPhone/iPad 应用程序时,我使用 XCode 工具栏上的“停止”按钮(产品 | 停止)退出应用程序。在此之后,XCod
我刚刚下载了android开放源代码项目,并尝试使用make来构建它,我收到了以下消息: build/core/prebuilt.mk:91: *** recipe commences before
我以前从未制作过 makefile,但我们已经收到了这个,但是,如果我尝试运行它,它只会说, missing separator. stop. 我不知道可能出了什么问题 - 我已经确保空格只按制表符。
好吧,这段代码非常基本。用户将答案输入文本框,如果等于“第一+第二”,他们就得到一分。然后,他们有 5 秒钟的时间回答下一个数学问题。如果他们这样做了,函数“doCalculation”将再次运行,他
我在 viewController 中有一个循环动画 - (void)moveAnimating { [UIView animateWithDuration:2.0f animations:^
当我有一个待处理的 ASIFormDataRequest(作为异步任务启动)仍在执行并且用户按下后退按钮(为了弹出 View )时,我的 viewController 出现问题。 有什么方法可以停止该
我们正在使用 flashdevelop 和 flash CS 3 开发基于 flash 的游戏。我们正在使用 flash CS3 发布 swc,swc 将作为库在 flashdevlop 中使用。 一
我在线程中有一个连接,因此我将其添加到运行循环中以获取所有数据: [[NSRunLoop currentRunLoop] run]; [connection scheduleInRunLoop
你好,我做了一个 php 套接字服务器来从 plc 获取数据,plc 被配置为 tcp 套接字客户端。 我有一个严重的问题,如果本地网络出现故障,似乎功能 socket_accept 停止,plc 无
这个问题已经有答案了: How to stop a setTimeout loop? (10 个回答) 已关闭 8 年前。 请帮助获得正确的函数或方法来停止 setTimeout 函数。 我一直在尝试
我正在运行一个多项目SBT(v0.13)构建,并且希望它在子项目中遇到的第一个错误(编译)时快速失败(停止)。 当前的行为是,当某项无法在子项目中进行编译时,构建将继续(以编译所有其他子项目)。 一旦
我有播放.wav文件中声音的代码,但是我无法停止播放歌曲,甚至无法退出程序直到播放结束。因为这是一首5分钟的歌曲,所以这是一个问题。这是我如何播放wav的代码: public class EasySo
我正在寻找一种解决方案,该如何控制从JSF应用程序播放音频文件。 我不需要完整的解决方案,只需引用我可以用来控制播放音频文件(开始/停止/更改声音)的组件即可。 我尝试搜索过去的问题,但没有成功。 我
我已经在test.ps1中编写了以下函数,在运行该脚本以启动/停止/ ..时我想做一个选择: function getState($SeviceName) { $server = @('hos
我必须设置一个 10 分钟的计时器,它会重定向到主屏幕。此外,它必须在每个操作(例如按下按钮)时重置。我找到了这个计时器:https://github.com/fengyuanchen/vue-cou
我正在制作一个聊天应用程序,功能之一就是发送声音。发送的HTML如下: LOL Stop Play 第一次发送时,“自动播放”效果很好。因此,现在我
我基本上希望页面能够接受用户输入的时间(以秒为单位)。 之后我希望当用户按下“开始”按钮时开始倒计时按下暂停按钮时“暂停”。还有一个重置按钮,以便用户可以从头开始倒计时。 这是我到目前为止得到的:
我需要停止 $.each 循环,加载图像,然后继续循环。我有 Canvas ,可以在其中加载对象图像。对象以正确的顺序排列在数组中。现在,当我尝试从数组加载对象时,存在一个问题:由于尺寸不同,并且它们
我是一名优秀的程序员,十分优秀!