Бесконечная прокрутка с новыми событиями в RxJS и Angular - PullRequest
0 голосов
/ 06 июня 2018

Принять почтовый ящик.50 самых последних электронных писем загружаются при начальной загрузке страницы.

С этого момента любые новые входящие электронные письма должны появляться в верхней части списка.

Сложный фактор заключается в том, что пользователь можетпролистайте, прокрутив вниз до нижней части страницы.Это загрузит следующую страницу данных в конец списка.

Мне было интересно, как этого можно добиться с помощью Angular и RxJS.Первоначально я хотел иметь Subject<Email>, на который я мог бы позвонить next(email), чтобы отправить его в поток, однако это не сработало, так как нам нужно и добавлять, и добавлять.

Еще один усложняющий факторзаключается в том, что новые электронные письма должны быть анимированными (то есть исчезать).

Я планировал сделать это следующим образом:

<email *ngFor="let email of (emails$ | async)">...</email>

Вместо этого я думаю изменить его на следующее:

<div class="new-emails" *ngFor="let email of (newEmails$ | async)">...</div>
<div class="initial-emails" *ngFor="let email of (initialEmails$ | async)">...</div>
<div class="older-emails" *ngFor="let email of (oldEmails$ | async)"></div>

Это стандартное решение проблемы или есть какой-то RxJS, который я мог бы упустить, чтобы упростить это?

1 Ответ

0 голосов
/ 06 июня 2018

Здравствуйте, в этом случае я бы, вероятно, использовал рекурсивную стратегию, такую ​​как thie CodeSandbox , демо использует Subject.

Вот фрагмент кода со структурой рекурсивного элемента, за которым следуетфиктивная служба запросов для фида данных.

В общем, я просто вызываю один и тот же элемент всякий раз, когда Subject в моем сервисе обновляется с .next(), хитрая часть такова, чтовы должны использовать pipe(first()) для вашей темы подписки , потому что в противном случае подписка не будет отменена, даже если вы добавили логику отмены подписки в onDestroy (уничтожить не вызов, потому что на самом деле выпросто погружайтесь все больше и больше в рекурсию без отсоединения какого-либо компонента), и это нарушит вашу логику визуализации.

// Typescript
import { Component, Input } from "@angular/core";
import { InfinityScrollFeedService } from "./../services/infinity-scroll-feed.service";
import { first } from "rxjs/operators";

@Component({
  selector: "app-recursive",
  templateUrl: "./recursive.component.html",
  styleUrls: ["./recursive.component.css"]
})
export class RecursiveComponent {
  @Input() initialData;
  @Input() page;
  nextLayer = [];

  constructor(private feed: InfinityScrollFeedService) {}

  ngOnInit() {
    this.feed.httpCallMocker.pipe(first()).subscribe(data => {
      this.nextLayer = data;
    });
  }

  loadMore() {
    this.feed.retrivePackage(Number(this.page) + 1);
  }
}
// Template

<div class="row" *ngFor="let row of initialData">
	<div>Name: {{row.name}}</div>
	<div>Age: {{row.age}}</div>
</div>

<div *ngIf="nextLayer.length > 0">
	<app-recursive [initialData]="nextLayer" [page]="(page+1)">
	</app-recursive>
</div>
<button *ngIf="nextLayer.length <= 0" (click)="loadMore()">Show more</button>

// Css 
.row {
  display: flex;
  justify-content: space-between;
  border: 1px solid red;
}

import { Injectable } from "@angular/core";
import { Subject } from "rxjs";

@Injectable()
export class InfinityScrollFeedService {
  dataPackages = [];

  someMokeNames = ["Hari", "Xapu", "Hristiyan", "Pesho", "Gosho", "Ivan"];

  httpCallMocker = <[]>new Subject();

  constructor() {}
  private getRandomNumber = max => {
    return Math.floor(Math.random() * Math.floor(max));
  };

  private addDataPackage = () => {
    let newData = [];
    for (let i = 0; i < 10; i++) {
      newData.push({
        name: this.someMokeNames[
          this.getRandomNumber(this.someMokeNames.length - 1)
        ],
        age: this.getRandomNumber(100)
      });
    }
    this.dataPackages.push(newData);
  };

  retrivePackage(page) {
    if (this.dataPackages.length <= page) {
      this.addDataPackage();
    }
    this.httpCallMocker.next(this.dataPackages[page]);
  }
}
...