Реализация директивы в Angular 4 для непрерывного циклического переключения цветов фона на хосте

Я изучаю angular 4 и хотел бы реализовать директиву, которая заставляет цвета фона элемента хоста циклически перемещаться по 7, перечисленным в массиве. В идеале я хотел бы, чтобы это было непрерывным. Я не знаю, к каким крючкам жизненного цикла мне нужно подключиться. Вот что у меня на данный момент. В настоящее время он даже не виден циклически через 7 раз, с интервалом в одну секунду, как ожидалось при использовании SetTimeOut, Я закомментировал While блок как то просто вешает браузер.

import {
  Directive,
  OnInit,
  HostBinding,
  Input
} from '@angular/core';


@Directive({
  selector: '[rainbowize]'
})
export class RainbowizeDirective {
  colors: Array<string>;

 @HostBinding('style.backgroundColor') bgColor: string;

  constructor() {
    this.colors = ['violet', 'indigo', 'blue', 'green', 'yellow', 'orange', 'red'];
 }

 ngOnInit(){
   let that = this;
   //while (true) {
      for (let i = 0; i < 7; i++) {
        console.log(that.colors[i]);
        setTimeout(function () {
          that.bgColor = that.colors[i];
        }, 1000)
      }
    //}
  }
}

HTML:

<h2 rainbowize >This is a raibowized paragraph</h2>

1 ответ

Решение

Вот как вы можете это сделать:

ngOnInit() {
    let that = this;
    let counter = 0;
    let length = this.colors.length;

    upd();

    function upd() {
        that.bgColor = that.colors[counter % length];
        counter++;

        // some stopping condition here
        if (counter < 20) {
            setTimeout(upd, 1000);
        }
    }
}

Самая важная вещь здесь - эта строка:

that.colors[counter % length];

Я использую оператор по модулю %, который возвращает остаток после целочисленного деления. Итак, он вернется:

0%7 = 0
1%7 = 1
2%7 = 2
...
6%7 = 6
7%7 = 0  <---- here the sequence starts from the beginning
8%7 = 1

Это будет работать до counter переменная достигает Number.MAX_SAFE_INTEGER, который 9007199254740991,

Другой более простой подход может заключаться в следующем:

    that.bgColor = that.colors[counter % length];
    counter++;

    if (counter === length) {
        counter = 0;
    }

Или используйте круговой связанный список.

Но мне все еще не ясно, где находится моя ошибка? Это потому, что у меня есть код в основной части ngOnInit, а не функция там?

Проблема с вашим кодом не имеет ничего общего с Angular. Это то, что вы добавляете все обратные вызовы, которые будут выполнены в течение секунды. И поскольку все они выполняются очень быстро, вы видите только последнее изменение красного цвета. Вы можете исправить это так:

  for (let i = 0; i < 7; i++) {
    console.log(that.colors[i]);
    setTimeout(function () {
      that.bgColor = that.colors[i];
    }, 1000*i+1)
       ^^^^^^ --------------
  }

Но проблема остается, что ваш цикл выполняется только один раз, поэтому каждый обратный вызов запланирован только один раз.

Другие вопросы по тегам