【问题标题】:Infinite scrolling with new events in RxJS and AngularRxJS 和 Angular 中的新事件无限滚动
【发布时间】:2018-06-06 02:57:42
【问题描述】:

假设一个电子邮件收件箱。初始页面加载时会加载 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 来简化此问题?

【问题讨论】:

  • 我认为最好不要绑定订阅本身,而是在包含所有电子邮件的类中创建一个数组,并使用 2 个 getter - 一个用于获取新电子邮件,第二个用于其他电子邮件(通过过滤单个数组)。此外,初始电子邮件和旧电子邮件不需要 2 个 div。两者都使用单个 div。这是我的看法

标签: angular rxjs observable reactive-programming


【解决方案1】:

您好,对于这种情况,我可能会使用像 thie CodeSandbox 这样的递归策略,演示使用的是主题。

这是一个包含递归项结构的片段,后面是用于数据馈送的模拟请求服务。

总的来说,每当我的服务中的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]);
  }
}

【讨论】:

    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 2014-12-04
    • 1970-01-01
    • 2018-09-21
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    • 2013-01-15
    相关资源
    最近更新 更多