如何在 Angular 2 中强制重新渲染组件?
How to force a component's re-rendering in Angular 2?
如何在 Angular 2 中强制重新渲染组件?
出于使用 Redux 进行调试的目的,我想强制组件重新呈现它的视图,这可能吗?
tx,找到了我需要的解决方法:
constructor(private zone:NgZone) {
// enable to for time travel
this.appStore.subscribe((state) => {
this.zone.run(() => {
console.log('enabled time travel');
});
});
运行 zone.run 会强制组件重新渲染
渲染发生在更改检测之后。要强制更改检测,以便将已更改的组件 属性 值传播到 DOM(然后浏览器将在视图中呈现这些更改),这里有一些选项:
- ApplicationRef.tick() - 类似于 Angular 1 的
$rootScope.$digest()
-- 即检查完整的组件树
- NgZone.run(callback) - 类似于
$rootScope.$apply(callback)
-- 即,评估 Angular 2 区域内的回调函数。我认为,但我不确定,这最终会在执行回调函数后检查完整的组件树。
- ChangeDetectorRef.detectChanges() - 类似于
$scope.$digest()
-- 即仅检查此组件及其子组件
您需要将 ApplicationRef
、NgZone
或 ChangeDetectorRef
导入然后注入您的组件。
对于您的特定情况,如果仅更改了一个组件,我会推荐最后一个选项。
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();
}
}
此处的其他答案提供了触发更改检测周期的解决方案,该周期将更新组件的视图(这与完全重新渲染不同)。
完全重新渲染,这将销毁和重新初始化组件(调用所有生命周期挂钩和重建视图)可以通过以下方式使用 ng-template
、ng-container
和 ViewContainerRef
来完成:
<div>
<ng-container #outlet >
</ng-container>
</div>
<ng-template #content>
<child></child>
</ng-template>
然后在引用了 #outlet
和 #content
的组件中,我们可以清除 outlets 的内容并插入另一个子组件实例:
@ViewChild("outlet", {read: ViewContainerRef}) outletRef: ViewContainerRef;
@ViewChild("content", {read: TemplateRef}) contentRef: TemplateRef<any>;
private rerender() {
this.outletRef.clear();
this.outletRef.createEmbeddedView(this.contentRef);
}
此外,应在 AfterContentInit
挂钩上插入初始内容:
ngAfterContentInit() {
this.outletRef.createEmbeddedView(this.contentRef);
}
可以在此处找到完整的工作解决方案https://stackblitz.com/edit/angular-component-rerender。
我使用 *ngIf 强制重新加载我的组件。
我容器中的所有组件都返回到完整的生命周期挂钩。
在模板中:
<ng-container *ngIf="_reload">
components here
</ng-container>
然后在ts文件中:
public _reload = true;
private reload() {
setTimeout(() => this._reload = false);
setTimeout(() => this._reload = true);
}
ChangeDetectorRef.detectChanges()
通常是最集中的做法。 ApplicationRef.tick()
通常过于武断。
要使用 ChangeDetectorRef.detectChanges()
,您需要在组件顶部添加:
import { ChangeDetectorRef } from '@angular/core';
... 然后,通常你在将它注入构造函数时使用别名,如下所示:
constructor( private cdr: ChangeDetectorRef ) { ... }
然后,在合适的地方,你可以这样称呼它:
this.cdr.detectChanges();
您称之为 ChangeDetectorRef.detectChanges()
的 可能非常重要。您需要完全 了解生命周期以及您的应用程序的确切运作方式和渲染组件的方式。这里没有什么可以替代完全完成您的作业并确保您彻底理解 Angular 生命周期。然后,一旦你理解了这一点,你就可以适当地使用ChangeDetectorRef.detectChanges()
(有时很容易理解你应该在哪里使用它,其他时候它可能非常复杂)。
如何在 Angular 2 中强制重新渲染组件? 出于使用 Redux 进行调试的目的,我想强制组件重新呈现它的视图,这可能吗?
tx,找到了我需要的解决方法:
constructor(private zone:NgZone) {
// enable to for time travel
this.appStore.subscribe((state) => {
this.zone.run(() => {
console.log('enabled time travel');
});
});
运行 zone.run 会强制组件重新渲染
渲染发生在更改检测之后。要强制更改检测,以便将已更改的组件 属性 值传播到 DOM(然后浏览器将在视图中呈现这些更改),这里有一些选项:
- ApplicationRef.tick() - 类似于 Angular 1 的
$rootScope.$digest()
-- 即检查完整的组件树 - NgZone.run(callback) - 类似于
$rootScope.$apply(callback)
-- 即,评估 Angular 2 区域内的回调函数。我认为,但我不确定,这最终会在执行回调函数后检查完整的组件树。 - ChangeDetectorRef.detectChanges() - 类似于
$scope.$digest()
-- 即仅检查此组件及其子组件
您需要将 ApplicationRef
、NgZone
或 ChangeDetectorRef
导入然后注入您的组件。
对于您的特定情况,如果仅更改了一个组件,我会推荐最后一个选项。
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();
}
}
此处的其他答案提供了触发更改检测周期的解决方案,该周期将更新组件的视图(这与完全重新渲染不同)。
完全重新渲染,这将销毁和重新初始化组件(调用所有生命周期挂钩和重建视图)可以通过以下方式使用 ng-template
、ng-container
和 ViewContainerRef
来完成:
<div>
<ng-container #outlet >
</ng-container>
</div>
<ng-template #content>
<child></child>
</ng-template>
然后在引用了 #outlet
和 #content
的组件中,我们可以清除 outlets 的内容并插入另一个子组件实例:
@ViewChild("outlet", {read: ViewContainerRef}) outletRef: ViewContainerRef;
@ViewChild("content", {read: TemplateRef}) contentRef: TemplateRef<any>;
private rerender() {
this.outletRef.clear();
this.outletRef.createEmbeddedView(this.contentRef);
}
此外,应在 AfterContentInit
挂钩上插入初始内容:
ngAfterContentInit() {
this.outletRef.createEmbeddedView(this.contentRef);
}
可以在此处找到完整的工作解决方案https://stackblitz.com/edit/angular-component-rerender。
我使用 *ngIf 强制重新加载我的组件。
我容器中的所有组件都返回到完整的生命周期挂钩。
在模板中:
<ng-container *ngIf="_reload">
components here
</ng-container>
然后在ts文件中:
public _reload = true;
private reload() {
setTimeout(() => this._reload = false);
setTimeout(() => this._reload = true);
}
ChangeDetectorRef.detectChanges()
通常是最集中的做法。 ApplicationRef.tick()
通常过于武断。
要使用 ChangeDetectorRef.detectChanges()
,您需要在组件顶部添加:
import { ChangeDetectorRef } from '@angular/core';
... 然后,通常你在将它注入构造函数时使用别名,如下所示:
constructor( private cdr: ChangeDetectorRef ) { ... }
然后,在合适的地方,你可以这样称呼它:
this.cdr.detectChanges();
您称之为 ChangeDetectorRef.detectChanges()
的 可能非常重要。您需要完全 了解生命周期以及您的应用程序的确切运作方式和渲染组件的方式。这里没有什么可以替代完全完成您的作业并确保您彻底理解 Angular 生命周期。然后,一旦你理解了这一点,你就可以适当地使用ChangeDetectorRef.detectChanges()
(有时很容易理解你应该在哪里使用它,其他时候它可能非常复杂)。