Angular 10 - 如何在集合更改时自动加载新项目

Posted

技术标签:

【中文标题】Angular 10 - 如何在集合更改时自动加载新项目【英文标题】:Angular 10 - How to auto load new items when collection changes 【发布时间】:2021-03-03 11:42:59 【问题描述】:

这个想法是,当用户滚动到页面底部时,它应该添加更多项目。 我在 onScroll() 方法的 posts 变量中添加了更多项目,但我无法弄清楚 html 模板将如何自动加载新项目。

home-component.component.ts

import  Component, OnInit  from '@angular/core';
import  Post  from '../post';

@Component(
  selector: 'home-component',
  templateUrl: './home-component.component.html',
  styleUrls: ['./home-component.component.css']
)
export class HomeComponentComponent implements OnInit 
  numbers(n: number): number[] 
    return [...Array(n).keys()];
  
  page: number = 1;
  posts: Post[] = [];

  constructor() 
    for (let i = 1; i <= 30; i++) 
      let imgNo = ((2 * i) % 3) + 1;
      let p = new Post;
      p.userName = "username" + i;
      p.profileIconURL = "../assets/images/dp.png";
      p.postImageURL = "../assets/images/post" + imgNo + ".png";
      p.postMessage = "message for the post " + i + "...";
      p.noOfLikes = 2 * i;
      this.posts.push(p);
    
  

  ngOnInit(): void 
  

  onScroll() 
    //this.page++;
    for (let i = 1; i <= 3; i++) 
      let imgNo = ((2 * i) % 3) + 1;
      let p = new Post;
      p.userName = "username" + i;
      p.profileIconURL = "../assets/images/dp.png";
      p.postImageURL = "../assets/images/post" + imgNo + ".png";
      p.postMessage = "message for the post " + i + "...";
      p.noOfLikes = 2 * i;
      this.posts.push(p);
    
  

home-component.component.html

<span *ngFor="let post of posts">
  <post-component [userName]="post.userName"
                  [profileIconURL]="post.profileIconURL"
                  [postImageURL]="post.postImageURL"
                  [postMessage]="post.postMessage"
                  [noOfLikes]="post.noOfLikes"
  >
  </post-component>
</span>

【问题讨论】:

您可以使用 rxjs observables 和 Angular 异步管道的强大功能 【参考方案1】:

您可以使用 rxjs 可观察对象,也可以使用更改检测策略让 HTML 知道数据已更改。

import ChangeDetectorRef from @angular/core
...

constructor (private cdRef: ChangeDetectorRef) 
..

onListLoad() 
... Loading algorithm
this.cdRef.detectChanges()

这就是你可以使用它的方式。 Change Detector 会通知 HTML 页面它必须重新加载自己。

您还可以阅读有关 Angular 中虚拟滚动的更多信息,它可以更优雅地处理它,并且始终管理 DOM 上的负载。这是一个article,可以帮助您。

【讨论】:

我开始工作了。我会尽快发布我的答案。但我会检查文章以了解想法。谢谢。【参考方案2】:

我让它工作了。这个post 帮助了。

home-component.component.ts

import  Component, OnInit  from '@angular/core';
import  Post  from '../post';
import  Observable, BehaviorSubject, of  from 'rxjs';
import  take  from 'rxjs/operators';
import  HostListener  from '@angular/core';

@Component(
  selector: 'app-home-component',
  templateUrl: './home-component.component.html',
  styleUrls: ['./home-component.component.css']
)
export class HomeComponentComponent implements OnInit 
  numbers(n: number): number[] 
    return [...Array(n).keys()];
  
  page: number = 1;
  posts: Post[] = [];
  subject: BehaviorSubject<any[]> = new BehaviorSubject<any>([]);
  array$: Observable<any> =  this.subject.asObservable();

  constructor() 
    for (let i = 1; i <= 5; i++) 
      let imgNo = ((2 * i) % 3) + 1;
      let p = new Post;
      p.userName = "username" + i;
      p.profileIconURL = "../assets/images/dp.png";
      p.postImageURL = "../assets/images/post" + imgNo + ".png";
      p.postMessage = "message for the post " + i + "...";
      p.noOfLikes = 2 * i;
      //this.posts.push(p);
      this.addElementToObservableArray(p);
      console.log(i);
    
  

@HostListener('window:scroll', ['$event']) onScrollEvent(event: any)
  //https://***.com/questions/41304968/how-to-get-on-scroll-events

  let pos = (document.documentElement.scrollTop || document.body.scrollTop) + document.documentElement.offsetHeight;
  let scrolltop = (document.documentElement.scrollTop || document.body.scrollTop);
  let max = document.documentElement.scrollHeight;
  let windowheight = window.innerHeight;
  let isbottom = scrolltop + windowheight == max;
  let istop = scrolltop == 0;
  console.log(pos + "," + max + "," + document.documentElement.offsetHeight + "," + scrolltop);

   if(isbottom )   
      //console.log("End");
      this.page++;
      console.log(this.page);
      for (let i = this.page; i < this.page+5; i++) 
        let imgNo = ((2 * i) % 3) + 1;
        let p = new Post;
        p.userName = "username" + i;
        p.profileIconURL = "../assets/images/dp.png";
        p.postImageURL = "../assets/images/post" + imgNo + ".png";
        p.postMessage = "message for post " + i + "...";
        p.noOfLikes = 2 * i;
        //this.posts.push(p);
        this.addElementToObservableArray(p);
      
 


  ngOnInit(): void 
  

  addElementToObservableArray(item) 
    this.array$.pipe(take(1)).subscribe(val => 
      console.log(val)
      const newArr = [...val, item];
      this.subject.next(newArr);
    )
  

home-component.component.html

<div *ngFor="let post of array$ | async">
  <app-post-component [userName]="post.userName"
                  [profileIconURL]="post.profileIconURL"
                  [postImageURL]="post.postImageURL"
                  [postMessage]="post.postMessage"
                  [noOfLikes]="post.noOfLikes"
  >
  </app-post-component>
</div>

post-component.component.ts

import  Component, OnInit, Input  from '@angular/core';
import  Post  from '../post'

@Component(
  selector: 'app-post-component',
  templateUrl: './post-component.component.html',
  styleUrls: ['./post-component.component.css']
)
export class PostComponentComponent implements OnInit 
  @Input() userName: string;
  @Input() profileIconURL: string;
  @Input() postImageURL: string;
  @Input() postMessage: string;
  @Input() noOfLikes;
  @Input() comments;

  @Input() post: any;

  constructor() 
    this.userName = "Test user";
    this.profileIconURL = "../assets/images/dp.png";
    this.postImageURL = "../assets/images/postdefault.png";
    this.noOfLikes = 0;
    this.postMessage = "post message...";
    this.comments = "";
  

  ngOnInit(): void 
  


post-component.component.html

<div class="container text-center py-4" style="width:480px;">
  <div class="card bg-white rounded border bg-primary">
    <div class="row">
      <div class="col-md-2 text-left ml-2"><img src="profileIconURL" ></div>
      <div class="col-md-7 text-left justify-content-left d-flex align-items-center p-0">userName</div>
      <div class="col-md-2 mr-2">
        <div class="float-right">...</div>
      </div>
    </div>
    <div class="row">
      <div class="col" style="height:400px;"><img src="postImageURL"  ></div>
    </div>
    <div class="row">
      <div class="col text-left ml-2">noOfLikes Likes</div>
    </div>
    <div class="row">
      <div class="col text-left ml-2">postMessage</div>
    </div>
  </div>
</div>

post.ts

export class Post 
  id: number;
  userName: string;
  profileIconURL: string;
  postImageURL: string;
  postMessage: string;
  noOfLikes: number;

  constructor() 
    this.id = 0;
    this.userName = "Test user";
    this.profileIconURL = "../assets/images/dp.png";
    this.postImageURL = "../assets/images/postdefault.png";
    this.noOfLikes = 0;
    this.postMessage = "braydoncoyer I can't wait to see the new Star Wars movie.";
  

【讨论】:

以上是关于Angular 10 - 如何在集合更改时自动加载新项目的主要内容,如果未能解决你的问题,请参考以下文章

文件更改时如何自动重新加载Django?

如何在没有 jquery 的情况下在 Angular 中的页面加载时自动打开 HTML 日历

Angular 9 在每次更改时滚动到顶部

使用 Angular 10 部署后为客户端自动重新加载

设备方向更改时如何重新排列集合视图单元格

如何使用 Angular 延迟加载模块克服加载块失败的问题