如何手动重新渲染组件Angular 5

Smo*_*son 9 typescript angular

有没有一种方法可以手动重新渲染组件,例如当用户单击按钮时?

我已经看到了类似的帖子,但没有这些工作对我来说,例如这里

例如,

renderComponent() {
   // force component re-render
}
Run Code Online (Sandbox Code Playgroud)

Anh*_*yen 9

我为此重新渲染目的创建了一个指令

/**
 * Example:
 *
 * <ng-container *rerender='changingInput'>
 *    this content will be re-rendered everytime `changingInput` changes
 * </ng-container>
 */

import { Directive,
         Input,
         TemplateRef,
         ViewContainerRef } from '@angular/core';

@Directive({
  selector: '[rerender]'
})
export class RerenderDirective {
  constructor(
    private templateRef:    TemplateRef<any>,
    private viewContainer:  ViewContainerRef
  ) {}

  // if detects changes of the input `val`, clear and rerender the view
  @Input() set rerender(val) {
    this.viewContainer.clear();
    this.viewContainer.createEmbeddedView(this.templateRef);
  }
}
Run Code Online (Sandbox Code Playgroud)

查看我的要点以获取最新更新。

  • 谢谢 - 我已经找了差不多一年了!调用 ChangeDetectorRef 方法不起作用 (2认同)

Vol*_*hat 7

如果我对您的理解不正确,您会询问ChangeDetectionStrategy Angular有两种选择

enum ChangeDetectionStrategy {
  OnPush: 0
  Default: 1
}
Run Code Online (Sandbox Code Playgroud)

如果您使用默认值,则它将在每次事件(例如单击)之后“重新渲染”您查看。

如果您使用的是OnPush,如果将observable与|一起使用,它将重新渲染。异步,也可以注入 ChangeDetectorRef和“询问”以重新呈现

constructor(private ref: ChangeDetectorRef) {
    setInterval(() => {
      this.numberOfTicks++;
      // the following is required, otherwise the view will not be updated
      this.ref.markForCheck();
    }, 1000);
  }
Run Code Online (Sandbox Code Playgroud)

但这是正确的,如果您在angular中运行。有时,如果您正在收听外部服务并且在NgZone之外运行,则需要执行ngZone.run

this._ngZone.run(() => { console.log('Do change detection here'); });
Run Code Online (Sandbox Code Playgroud)


sug*_*rme 6

如果您打算操纵视图(添加,删除或重新附加),那么这里是一个示例:

import { Component, ViewContainerRef, AfterViewInit, ViewChild, ViewRef,TemplateRef} from '@angular/core';

import { ChildComponent } from './child.component';

@Component({
  selector: 'host-comp',
  template: `
    <h1>I am a host component</h1>

    <ng-container #vc><ng-container>

    <br>

    <button (click)="insertChildView()">Insert Child View</button>
    <button (click)="removeChildView()">Remove Child View</button>
    <button (click)="reloadChildView()">Reload Child View</button>

    <ng-template #tpl>
      <child-comp><child-comp>
    <ng-template>

  `
})
export class HostComponent implements AfterViewInit{

  @ViewChild('vc', {read: ViewContainerRef}) vc: ViewContainerRef;

  @ViewChild('tpl', {read: TemplateRef}) tpl: TemplateRef<any>;

  childViewRef: ViewRef;

  constructor(){}

  ngAfterViewInit(){
    this.childViewRef = this.tpl.createEmbeddedView(null);
  }

  insertChildView(){
    this.vc.insert(this.childViewRef);
  }

  removeChildView(){
    this.vc.detach();
  }

  reloadChildView(){
    this.removeChildView();
    setTimeout(() =>{
      this.insertChildView();
    }, 3000);
  }
}
Run Code Online (Sandbox Code Playgroud)

这里的例子

  • 超时只是明显地是可观的,还是异步所必需的? (2认同)

小智 6

超文本标记语言

<app-component1 *ngIf="FLAG"></app-component1>
Run Code Online (Sandbox Code Playgroud)

TS

  constructor(private changeDetectorRef: ChangeDetectorRef) {
      this.FLAG = true
  }

  renderComponent() {
      this.FLAG = false;
      this.changeDetectorRef.detectChanges();
      this.FLAG = true;
  }
Run Code Online (Sandbox Code Playgroud)


Sag*_*che 5

您可以使用detectChanges()markForCheck()告诉angular重新重新渲染组件。

  • ChangeDetectorRef 并没有真正重新渲染,它只是使用摘要周期更新数据绑定 (4认同)