如何强制组件在Angular 2中重新渲染?

bor*_*net 160 angular2-changedetection angular

如何强制组件在Angular 2中重新渲染?出于调试目的,使用Redux我想强制组件重新渲染它的视图,这可能吗?

Mar*_*cok 198

更改检测后进行渲染.要强制进行更改检测,以便已更改的组件属性值传播到DOM(然后浏览器将在视图中呈现这些更改),以下是一些选项:

  • ApplicationRef.tick() - 类似于Angular 1 $rootScope.$digest()- 即检查完整的组件树
  • NgZone.run(回调) - 类似于$rootScope.$apply(callback)- 即,评估Angular 2区域内的回调函数.我想,但我不确定,这最终会在执行回调函数后检查完整的组件树.
  • ChangeDetectorRef.detectChanges() - 类似于$scope.$digest()- 即,仅检查此组件及其子组件

您将需要进口,然后注入ApplicationRef,NgZoneChangeDetectorRef为您的组件.

对于您的特定场景,如果只有一个组件发生了变化,我会推荐最后一个选项.

  • 尝试所有这些,但仍然没有在ios上工作,伤心 (3认同)
  • ChangeDetectorRef 上有 Angular2 最终版本的工作代码吗?我现在面临的情况是,在 http 的 post 请求创建新用户之后,视图不会更新,然后成功将新对象推送到现有的旧用户列表(用于在视图中迭代)。很奇怪的是“这是我第一次遇到在 ng2 中无法运行的更新”。更改检测策略是默认的,所以我知道我没有搞乱更改检测策略。 (2认同)

bor*_*net 45

tx,找到了我需要的解决方法:

  constructor(private zone:NgZone) {
    // enable to for time travel
    this.appStore.subscribe((state) => {
        this.zone.run(() => {
            console.log('enabled time travel');
        });
    });
Run Code Online (Sandbox Code Playgroud)

运行zone.run将强制组件重新渲染

  • 什么是appStore在这个上下文中 - 哪种变量及其类型?似乎是可观察的...但我的observable是在我想要点击一个按钮刷新的组件内...我不知道如何从父/当前位置访问子组件方法/变量 (5认同)

loo*_*nis 26

我使用 *ngIf 强制重新加载我的组件。

我的容器内的所有组件都返回到完整的生命周期钩子。

在模板中:

<ng-container *ngIf="_reload">
    components here 
</ng-container>
Run Code Online (Sandbox Code Playgroud)

然后在 ts 文件中:

public _reload = true;

private reload() {
    setTimeout(() => this._reload = false);
    setTimeout(() => this._reload = true);
}
Run Code Online (Sandbox Code Playgroud)


Fen*_*ang 18

ChangeDetectorRef方法

import { Component, OnInit, ChangeDetectorRef } from '@angular/core';

export class MyComponent {

    constructor(private cdr: ChangeDetectorRef) { }

    selected(item: any) {
        if (item == 'Department')
            this.isDepartment = true;
        else
            this.isDepartment = false;
        this.cdr.detectChanges();
    }

}
Run Code Online (Sandbox Code Playgroud)


Chr*_*row 13

ChangeDetectorRef.detectChanges()通常是最集中的方法。ApplicationRef.tick()通常是过于大锤的方法。

要使用ChangeDetectorRef.detectChanges(),您需要在组件顶部添加它:

import {  ChangeDetectorRef } from '@angular/core';
Run Code Online (Sandbox Code Playgroud)

...然后,通常当您将其注入到构造函数中时,您通常会使用别名,如下所示:

constructor( private cdr: ChangeDetectorRef ) { ... }

然后,在适当的地方,您可以这样称呼它:

this.cdr.detectChanges();
Run Code Online (Sandbox Code Playgroud)

您致电的地点ChangeDetectorRef.detectChanges()可能非常重要。您需要完全了解生命周期以及应用程序如何运行和呈现其组件。这里没有什么可以替代彻底做好功课并确保您彻底了解 Angular 生命周期。然后,一旦你理解了这一点,你就可以ChangeDetectorRef.detectChanges()适当地使用它(有时很容易理解应该在哪里使用它,有时它可能非常复杂)。


Pav*_*cki 8

这里的其他答案提供了触发变更检测周期的解决方案,该周期将更新组件的视图(与完全重新渲染不同)。

完全重新绘制,这将破坏并重新初始化组件(调用所有生命周期挂钩,并重建视图)可以通过使用来完成ng-templateng-container并且ViewContainerRef在下列方式:

<div>
  <ng-container #outlet >
  </ng-container>
</div>

<ng-template #content>
  <child></child>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

然后在同时引用这两个组件的组件中#outlet#content我们可以清除出口的内容并插入子组件的另一个实例:

@ViewChild("outlet", {read: ViewContainerRef}) outletRef: ViewContainerRef;
@ViewChild("content", {read: TemplateRef}) contentRef: TemplateRef<any>;

private rerender() {
    this.outletRef.clear();
    this.outletRef.createEmbeddedView(this.contentRef);
}
Run Code Online (Sandbox Code Playgroud)

另外,初始内容应插入到AfterContentInit钩子上:

ngAfterContentInit() {
    this.outletRef.createEmbeddedView(this.contentRef);
}
Run Code Online (Sandbox Code Playgroud)

完整的工作解决方案可以在这里找到https://stackblitz.com/edit/angular-component-rerender