首页 > 解决方案 > update html binding after each change in typescript

问题描述

i'm trying to make typing animation using typescript that append next character from string every 200ms.

i read alot of solutions that talk about zone and ChangeDetectorRef but nothing work.

the problem is the whole string is shown after finish the process showing the final result (no animation :( )

Edit :

i'm using Angular 2.

this is my simple app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = '';
  nots="app works!";

constructor(private ref: ChangeDetectorRef){
  setTimeout(() => {


  this.sleep(200);
    this.title='a';
    this.ref.detectChanges();

     this.sleep(200);
    this.title+='a';
    this.ref.detectChanges();

      this.sleep(200);
    this.title+='a';
    this.ref.detectChanges();

      this.sleep(200);
    this.title+='a';
    this.ref.detectChanges();

      this.sleep(200);
    this.title+='a'; 
    this.ref.detectChanges();

    console.log(3);
 }, 1000);    
}

 sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
}

you can see i want to show aaaaa like this : a aa aaa aaa aaaaa . any help ?

标签: angulartypescript

解决方案


Here is one approach that you might want to try:

import { Component } from '@angular/core';
import { interval } from 'rxjs';
import { take } from 'rxjs/operators';


@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  name = '';
  ngOnInit() {
    interval(500)
    .pipe(
      take(5)
    )
    .subscribe(_ =>
      this.name += 'a'
    );
  }
 }

demo https://stackblitz.com/edit/angular-6pkbhk?file=src%2Fapp%2Fapp.component.ts

Alternatively, you can still use plain old promise appraoch, which sticks more closely to your original approach,

  import { Component } from '@angular/core';
  import { interval } from 'rxjs';
  import { take } from 'rxjs/operators';


  @Component({
    selector: 'my-app',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
  })
  export class AppComponent {
    title = '';
    ngOnInit() {

      this.sleep(200)
        .then(() => this.title = 'a')
        .then(() => this.sleep(200))
        .then(() => this.title += 'a')
        .then(() => this.sleep(200))
        .then(() => this.title += 'a')
        .then(() => this.sleep(200))
        .then(() => this.title += 'a')
        .then(() => this.sleep(200))
        .then(() => this.title += 'a')

   // same as 
  /*  let promise: any = this.sleep(delay)
      .then(() => this.title = 'a');

    for (let i = 0; i < 4; i++) {
      promise = promise
        .then(() => this.sleep(delay))
        .then(() => this.title += 'a')
    } */
    }

    sleep(milliseconds) {
      let resolve;
      let promise = new Promise((_resolve) => {
        resolve = _resolve;
      });
      setTimeout(() => resolve(), milliseconds);
      return promise;
    }
  }

demo https://stackblitz.com/edit/angular-d8ur5y?file=src%2Fapp%2Fapp.component.ts


推荐阅读