mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 05:21:52 +08:00
docs(virtual-scroll): update performance tips
This commit is contained in:
@ -102,25 +102,25 @@ import { VirtualFooter, VirtualHeader, VirtualItem } from './virtual-item';
|
|||||||
*
|
*
|
||||||
* ### Images Within Virtual Scroll
|
* ### Images Within Virtual Scroll
|
||||||
*
|
*
|
||||||
* Ionic provides `<ion-img>` to manage HTTP requests and image rendering.
|
* HTTP requests, image decoding, and image rendering can cause jank while
|
||||||
* Additionally, it includes a customizable placeholder element which shows
|
* scrolling. In order to better control images, Ionic provides `<ion-img>`
|
||||||
* before the image has finished loading. While scrolling through items
|
* to manage HTTP requests and image rendering. While scrolling through items
|
||||||
* quickly, `<ion-img>` knows not to make any image http requests, and only
|
* quickly, `<ion-img>` knows when and when not to make requests, when and
|
||||||
* loads the images that are viewable after scrolling.
|
* when not to render images, and only loads the images that are viewable
|
||||||
|
* after scrolling. [Read more about `ion-img`.](../img/Img/)
|
||||||
*
|
*
|
||||||
* It's also important for app developers to ensure image sizes are locked in,
|
* It's also important for app developers to ensure image sizes are locked in,
|
||||||
* and after images have fully loaded they do not change size and affect any
|
* and after images have fully loaded they do not change size and affect any
|
||||||
* other element sizes. Simply put, to ensure rendering bugs are not introduced,
|
* other element sizes. Simply put, to ensure rendering bugs are not introduced,
|
||||||
* it's vital that elements within a virtual item does not dynamically change.
|
* it's vital that elements within a virtual item does not dynamically change.
|
||||||
*
|
*
|
||||||
* We recommend using our `<ion-img>` element over the native `<img>` element
|
* For virtual scrolling, the natural effects of the `<img>` are not desirable
|
||||||
* because when an `<img>` element is added to the DOM, it immediately
|
* features. We recommend using the `<ion-img>` component over the native
|
||||||
* makes a HTTP request for the image file. HTTP requests, image
|
* `<img>` element because when an `<img>` element is added to the DOM, it
|
||||||
* decoding, and image rendering can cause issues while scrolling. For virtual
|
* immediately makes a HTTP request for the image file. Additionally, `<img>`
|
||||||
* scrolling, the natural effects of the `<img>` are not desirable features.
|
* renders whenever it wants which could be while the user is scrolling. However,
|
||||||
*
|
* `<ion-img>` is governed by the containing `ion-content` and does not render
|
||||||
* Note: `<ion-img>` should only be used with Virtual Scroll. If you are using
|
* images while scrolling quickly.
|
||||||
* an image outside of Virtual Scroll you should use the standard `<img>` tag.
|
|
||||||
*
|
*
|
||||||
* ```html
|
* ```html
|
||||||
* <ion-list [virtualScroll]="items">
|
* <ion-list [virtualScroll]="items">
|
||||||
@ -157,25 +157,55 @@ import { VirtualFooter, VirtualHeader, VirtualItem } from './virtual-item';
|
|||||||
* ```
|
* ```
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* ### Performance Tips
|
* ## Virtual Scroll Performance Tips
|
||||||
*
|
*
|
||||||
* - When deploying to iOS with Cordova, it's highly recommended to use the
|
* #### iOS Cordova WKWebView
|
||||||
|
*
|
||||||
|
* When deploying to iOS with Cordova, it's highly recommended to use the
|
||||||
* [WKWebView plugin](http://blog.ionic.io/cordova-ios-performance-improvements-drop-in-speed-with-wkwebview/)
|
* [WKWebView plugin](http://blog.ionic.io/cordova-ios-performance-improvements-drop-in-speed-with-wkwebview/)
|
||||||
* in order to take advantage of iOS's higher performimg webview.
|
* in order to take advantage of iOS's higher performimg webview. Additionally,
|
||||||
* - Use `<ion-img>` rather than `<img>` so images are lazy loaded
|
* WKWebView is superior at scrolling efficiently in comparision to the older
|
||||||
* while scrolling.
|
* UIWebView.
|
||||||
* - Image sizes should be locked in, meaning the size of any element
|
*
|
||||||
* should not change after the image has loaded.
|
* #### Lock in element dimensions and locations
|
||||||
* - For the most part, ensure the element size for each virtual item
|
*
|
||||||
* does not dynamically change, but rather, their size must already be
|
* In order for virtual scroll to efficiently size and locate every item, it's
|
||||||
* locked in via CSS at the time they are rendered.
|
* very important every element within each virtual item does not dynamically
|
||||||
* - Provide an approximate width and height so the virtual scroll can
|
* change its dimensions or location. The best way to ensure size and location
|
||||||
* best calculate the cell height.
|
* does not change, it's recommended each virtual item has locked in its size
|
||||||
* - Changing the dataset requires the entire virtual scroll to be
|
* via CSS.
|
||||||
* reset, which is an expensive operation and should be avoided
|
*
|
||||||
* if possible.
|
* #### Use `ion-img` for images
|
||||||
* - Do not perform any DOM manipulation within section header and
|
*
|
||||||
* footer functions. These functions are called for every record in the
|
* When including images within Virtual Scroll, be sure to use
|
||||||
|
* [`ion-img`](../img/Img/) rather than the standard `<img>` HTML element.
|
||||||
|
* With `ion-img`, images are lazy loaded so only the viewable ones are
|
||||||
|
* rendered, and HTTP requests are efficiently controlled while scrolling.
|
||||||
|
*
|
||||||
|
* #### Set Approximate Widths and Heights
|
||||||
|
*
|
||||||
|
* As mentioned above, all elements should lock in their dimensions. However,
|
||||||
|
* virtual scroll isn't aware of the dimensions until after they have been
|
||||||
|
* rendered. For the initial render, virtual scroll still needs to set
|
||||||
|
* how many items should be built. With "approx" property inputs, such as
|
||||||
|
* `approxItemHeight`, we're able to give virtual sroll an approximate size,
|
||||||
|
* therefore allowing virtual scroll to decide how many items should be
|
||||||
|
* created.
|
||||||
|
*
|
||||||
|
* #### Changing dataset should use `virtualTrackBy`
|
||||||
|
*
|
||||||
|
* It is possible for the identities of elements in the iterator to change
|
||||||
|
* while the data does not. This can happen, for example, if the iterator
|
||||||
|
* produced from an RPC to the server, and that RPC is re-run. Even if the
|
||||||
|
* "data" hasn't changed, the second response will produce objects with
|
||||||
|
* different identities, and Ionic will tear down the entire DOM and rebuild
|
||||||
|
* it. This is an expensive operation and should be avoided if possible.
|
||||||
|
*
|
||||||
|
* #### Efficient headers and footer functions
|
||||||
|
*
|
||||||
|
* Each virtual item must stay extremely efficient, but one way to really
|
||||||
|
* kill its performance is to perform any DOM operations within section header
|
||||||
|
* and footer functions. These functions are called for every record in the
|
||||||
* dataset, so please make sure they're performant.
|
* dataset, so please make sure they're performant.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -183,7 +213,6 @@ import { VirtualFooter, VirtualHeader, VirtualItem } from './virtual-item';
|
|||||||
selector: '[virtualScroll]'
|
selector: '[virtualScroll]'
|
||||||
})
|
})
|
||||||
export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
|
export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
|
||||||
_trackBy: TrackByFn;
|
|
||||||
_differ: IterableDiffer;
|
_differ: IterableDiffer;
|
||||||
_scrollSub: any;
|
_scrollSub: any;
|
||||||
_scrollEndSub: any;
|
_scrollEndSub: any;
|
||||||
@ -216,7 +245,7 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
|
|||||||
set virtualScroll(val: any) {
|
set virtualScroll(val: any) {
|
||||||
this._records = val;
|
this._records = val;
|
||||||
if (isBlank(this._differ) && isPresent(val)) {
|
if (isBlank(this._differ) && isPresent(val)) {
|
||||||
this._differ = this._iterableDiffers.find(val).create(this._cd, this._trackBy);
|
this._differ = this._iterableDiffers.find(val).create(this._cd, this.virtualTrackBy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,9 +363,8 @@ export class VirtualScroll implements DoCheck, AfterContentInit, OnDestroy {
|
|||||||
/**
|
/**
|
||||||
* @input {function} Same as `ngForTrackBy` which can be used on `ngFor`.
|
* @input {function} Same as `ngForTrackBy` which can be used on `ngFor`.
|
||||||
*/
|
*/
|
||||||
@Input() set virtualTrackBy(val: TrackByFn) {
|
@Input() virtualTrackBy: TrackByFn;
|
||||||
this._trackBy = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _iterableDiffers: IterableDiffers,
|
private _iterableDiffers: IterableDiffers,
|
||||||
|
Reference in New Issue
Block a user