Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/449.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 离子5:VirtualScroll和图像缓存_Javascript_Angular_Ionic Framework_Capacitor_Ionic5 - Fatal编程技术网

Javascript 离子5:VirtualScroll和图像缓存

Javascript 离子5:VirtualScroll和图像缓存,javascript,angular,ionic-framework,capacitor,ionic5,Javascript,Angular,Ionic Framework,Capacitor,Ionic5,我正在构建一个应用程序(Ionic 5+Angular 9+Capactor),其中我有一长串包含图像和简短描述的卡片。 因此,在这种情况下,我必须使用虚拟滚动,因为长列表的页面加载速度太慢。 问题是,每次你上下滚动时,都会再次加载相同的图像(来自外部url),因此,如果你使用移动连接(3G等),这真的很糟糕。而且,如果你在办公室/断开连接,我想使用这些图像 我已经解决了,但是,如果你向下和向上滚动太快,正确的图像会被错误的图像替换。我认为这是因为虚拟卷轴 那么,如果我使用virtual scr

我正在构建一个应用程序(Ionic 5+Angular 9+Capactor),其中我有一长串包含图像和简短描述的卡片。 因此,在这种情况下,我必须使用虚拟滚动,因为长列表的页面加载速度太慢。 问题是,每次你上下滚动时,都会再次加载相同的图像(来自外部url),因此,如果你使用移动连接(3G等),这真的很糟糕。而且,如果你在办公室/断开连接,我想使用这些图像

我已经解决了,但是,如果你向下和向上滚动太快,正确的图像会被错误的图像替换。我认为这是因为虚拟卷轴

那么,如果我使用virtual scroll,您知道有什么好的解决方案可以用于图像缓存及其脱机使用吗?

首先,我想使用ServiceWorker,但如果在设备上构建应用程序,它就不起作用。有关此问题的更多信息,请参见此处:

我也发现了这个插件,但它不与离子5和电容器工作

所以,我现在的解决方案是这样的:

home.page.html:

<ion-virtual-scroll class="scroll" [items]="_filteredEvents" approxItemHeight="126px">
    <app-event-list-card *virtualItem="let event" [event]="event" [networkStatus]="_networkStatus" style="opacity:1"></app-event-list-card>
  </ion-virtual-scroll>

event-list-card.component.ts:

ngOnChanges(changes: SimpleChanges) {
      Storage.get({key: 'img' + this.event.id}).then((image) => {
        if (image.value) {
          this.event.image = image.value; // todo: do not assign a variable to event object
          this.changeDetectorRef.markForCheck();
        } else if(this.networkStatus) {
          this.convertImageToBase64(this.event.image).then((dataUrl: string) => {
            Storage.set({key: 'img' + this.event.id, value: dataUrl});
          });
          this.changeDetectorRef.markForCheck();
        } else {
          this.event.image = this.transparentImage;
        }
      });
  }

  private async convertImageToBase64(url): Promise<any> {
    const response = await fetch(url);
    const blob = await response.blob();
    const result = new Promise((resolve, reject) => {
      if (blob.type === 'text/html') {
        resolve(this.transparentImage);
      } else {
        const reader = new FileReader();
        reader.onloadend = () => resolve(reader.result);
        reader.onerror = () => reject;
        reader.readAsDataURL(blob);
      }
    });

    return await result;
  }
ngOnChanges(更改:SimpleChanges){
获取({key:'img'+this.event.id})。然后((image)=>{
if(image.value){
this.event.image=image.value;//todo:不要将变量分配给事件对象
this.changeDetectorRef.markForCheck();
}else if(此.networkStatus){
this.convertImageToBase64(this.event.image).then((dataUrl:string)=>{
set({key:'img'+this.event.id,值:dataUrl});
});
this.changeDetectorRef.markForCheck();
}否则{
this.event.image=this.transparentImage;
}
});
}
专用异步convertImageToBase64(url):承诺{
const response=等待获取(url);
const blob=wait response.blob();
const result=新承诺((解决、拒绝)=>{
if(blob.type=='text/html'){
解决(此为透明图像);
}否则{
const reader=new FileReader();
reader.onloadend=()=>解析(reader.result);
reader.onerror=()=>拒绝;
reader.readAsDataURL(blob);
}
});
返回等待结果;
}
event-list-card-component.html:

<ion-card *ngIf="event" [routerLink]="'/event-details/' + event.id" [class]="event.cancelled == 1 ? 'event-card__card event-card__card--cancelled' : 'event-card__card'">
    <ion-card-content class="event-card__inner">
      <ion-grid class="ion-no-padding">
        <ion-row class="ion-align-items-center">
          <ion-col size="5">
            <ion-thumbnail class="event-card__thumb">
              <!--<ion-img [src]="event.image" (ionError)="loadDefaultImage($event)" alt="Image - {{ event.name}}"></ion-img>-->
              <img [src]="sanitizer.bypassSecurityTrustResourceUrl(event.image)" onerror="this.src='data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'" crossorigin="anonymous">
            </ion-thumbnail>
          </ion-col>
          <ion-col size="7" class="event-card__description ion-no-padding">
            <ion-row class="ion-text-center">
              <h2 class="event-card__title">{{ (event.name) }}</h2>
            </ion-row>
            <ion-row class="ion-text-center">
              <h4 class="event-card__category">{{ event.event_type }}</h4>
            </ion-row>
            <ion-row class="ion-text-center">
              <h3 class="event-card__location">{{ event.location }}</h3>
            </ion-row>
          </ion-col>
        </ion-row>
      </ion-grid>
    </ion-card-content>
  </ion-card>

{{(event.name)}
{{event.event_type}
{{event.location}

我在这里使用onChanges是因为如果将onInit与virtual scroll一起使用,即使您有100个项目,它也只会执行大约10次–virtual scroll正在替换卡,而不是创建新卡。

作为缓存服务,在您发出请求后,将请求数据存储在jsonfile中,并将图像作为数据存储。然后,每次进入页面后,您将查看json数据,并在下一个条目中显示json数据,并发出http请求从apu获取数据,如果数据发生更改,则查看;如果数据发生更改,则清除jsonfile,然后重新填充新数据,从而可以轻松快速地刷新数据,并且查看将对用户友好(不会出现用户可能会发现的问题)否则保留json文件视图。这种方式不错,而且比可能导致应用程序崩溃的存储方式要好