Skip to main content

Pagination request strategy

stragety type

use hook

Before using extension hooks, make sure you are familiar with basic usage of alova.

A hook designed for paging scenarios, which can help you automatically manage paging data, preload data, reduce unnecessary data refresh, improve fluency by 300%, and reduce coding difficulty by 50%**. You can use it in the two paging scenarios of pull-down loading and page number flipping. This hook provides a wealth of features to help your application create better performance and more convenient paging functions.

Example

page list

Pull down to load more

Features

  • ✨ Rich and comprehensive paging status;
  • ✨ Rich and comprehensive pagination events;
  • ✨ Change page, pageSize to automatically get specified paging data;
  • ✨Data caching, no need to repeatedly request list data of the same parameters;
  • ✨ Front and back pages are preloaded, no waiting for page turning;
  • ✨Search condition monitoring automatically reacquires pages;
  • ✨ Support adding, editing and deleting list data;
  • ✨ Support refreshing the data of the specified page without reset;
  • ✨ Request-level search anti-shake, no need to maintain by yourself;

Install

# npm
npm install @alova/scene-vue --save
#yarn
yarn add @alova/scene-vue

Usage

Display list data

<template>
<div
v-for="item in data"
:key="item.id">
<span>{{ item.name }}</span>
</div>
<button @click="handlePrevPage">Previous page</button>
<button @click="handleNextPage">next page</button>
<button @click="handleSetPageSize">Set the number of pages</button>
<span>There are {{ pageCount }} pages</span>
<span>A total of {{ total }} data</span>
</template>

<script setup>
import { queryStudents } from './api.js';
import { usePagination } from '@alova/scene-vue';

const {
// loading state
loading,

// list data
data,

// is it the last page
// This parameter can be used to determine whether it needs to be loaded during pull-down loading
isLastPage,

// The current page number, changing this page number will automatically trigger the request
page,

// Number of data items per page
pageSize,

// number of paging pages
pageCount,

// total amount of data
total
} = usePagination(
// Method instance acquisition function, it will receive page and pageSize, and return a Method instance
(page, pageSize) => queryStudents(page, pageSize),
{
// Initial data before the request (data format returned by the interface)
initialData: {
total: 0,
data: []
},
initialPage: 1, // initial page number, default is 1
initialPageSize: 10 // The initial number of data items per page, the default is 10
}
);

// Turn to the previous page, the request will be sent automatically after the page value changes
const handlePrevPage = () => {
page.value--;
};

// Turn to the next page, the request will be sent automatically after the page value changes
const handleNextPage = () => {
page.value++;
};

// Change the number of pages, the request will be sent automatically after the pageSize value is changed
const handleSetPageSize = () => {
pageSize.value = 20;
};
</script>

Specify pagination data

The data structure returned by each paging data interface is different, so we need to tell usePagination the list data and the total number of items separately, so as to help us manage the paging data.

Suppose the data format returned by your paging interface is as follows:

interface PaginationData {
totalNumber: number;
list: any[];
}

At this point, you need to return the list data and the total number of items in the form of a function.

usePagination((page, pageSize) => queryStudents(page, pageSize), {
//...
total: response => response.totalNumber,
data: response => response.list
});

If you don't specify the total and data callback functions, they will get data in the following ways by default.

const total = response => response.total;
const data = response => response.data;
Caution

The data callback function must return a list of data, indicating the data set used in paging, and total is mainly used to calculate the current page number. If no number is returned in the total callback function, it will pass whether the number of requested lists is less than the pageSize value To determine whether the current page is the last page, which is generally used for pull-down loading.

Enable append mode

By default, the original list data will be replaced when the page is turned, and the append mode will append the data of the next page to the bottom of the current list when the page is turned. A common usage scenario is to pull down to load more.

usePagination((page, pageSize) => queryStudents(page, pageSize), {
//...
append: true
});

Preload adjacent page data

In order to provide a better experience for pagination, when the previous and next pages of the current page meet the conditions, it will be automatically preloaded, so that when the user turns the page, the data can be displayed directly without waiting. This is the default behavior. If you don't want to preload the data of adjacent pages, you can turn it off in the following way.

usePagination((page, pageSize) => queryStudents(page, pageSize), {
//...
preloadPreviousPage: false, // turn off preloading previous page data
preloadNextPage: false // turn off preloading next page data
});
preloading trigger conditions

When preloading switch is turned on, the next page will not be loaded blindly. The following two conditions need to be met:

  1. Preloading is based on cache of alova. The method instance used for pagination must enable chache. By default, get requests will have 5 minutes of memory cache. If it is a non-get request or the cache is turned off globally, you also need to set the cache in this Method. In the instance, set localCache separately to enable cache.
  2. Based on the total and pageSize parameters, it is determined that there is still data on the next page.

In addition to onSuccess, onError, onComplete request events, when preloading is triggered, you can also know the preloading status through fetching, and you can also listen to preloading request events through onFetchSuccess, onFetchError, onFetchComplete.

const {
// preload state
fetching,

// preload success event binding function
onFetchSuccess,

// preload error event binding function
onFetchError,

// Preloading complete event binding function
onFetchComplete
} = usePagination((page, pageSize) => queryStudents(page, pageSize), {
//...
});

Listening filter conditions

In many cases, the list needs to be filtered by conditions. At this time, the re-request can be triggered through the status monitoring of usePagination, which is the same as useWatcher provided by alova.

For example, filter by student name, student grade.

<template>
<input v-model="studentName" />
<select v-model="clsName">
<option value="1">Class 1</option>
<option value="2">Class 2</option>
<option value="3">Class 3</option>
</select>
<!-- ... -->
</template>

<script setup>
import { ref } from 'vue';
import { queryStudents } from './api.js';
import { usePagination } from '@alova/scene-vue';

// search condition status
const studentName = ref('');
const clsName = ref('');
const {
//...
} = usePagination((page, pageSize) => queryStudents(page, pageSize, studentName.value, clsName.value), {
//...
watchingStates: [studentName, clsName]
});
</script>

Same as useWatcher, you can also implement request debounce by specifying debounce, for details, please refer to useWatcher's debounce parameter setting.

usePagination((page, pageSize) => queryStudents(page, pageSize, studentName, clsName), {
//...
debounce: 300 // Anti-shake parameters, in milliseconds, can also be set as an array to set the anti-shake time separately for watchingStates
});

It should be noted that debounce is achieved by request debounce in useWatcher. **At the end of the monitoring state, there are two hidden monitoring states of page and pageSize, which can also be set by debounce. **

For example, when watchingStates is set to [studentName, clsName], [studentName, clsName, page, pageSize] will be monitored internally, so if you need to set anti-shake for page and pageSize, you can specify [0, 0, 500, 500].

Close initialization request

By default, usePagination will initiate a request during initialization, but you can also use immediate to turn it off, and then pass the send function, or change page or pageSize, and watchingStates, etc. state to initiate the request.

usePagination((page, pageSize) => queryStudents(page, pageSize, studentName, clsName), {
//...
immediate: false
});

List action functions

usePagination provides a fully functional list action function, which can achieve the same effect as the re-request list without re-requesting the list, which greatly improves the interactive experience of the page. The specific function description continues to look down!

Insert list item

You can use it to insert list items to any position in the list, and it will remove the last item after insertion to ensure the same effect as re-requesting the current page data.

/**
* Insert data
* If no index is passed in, it will be inserted at the front by default
* If a list item is passed in, it will be inserted after the list item, and an error will be thrown if the list item is not in the list data
* @param item insert item
* @param indexOrItem insertion position (index)
*/
declare function insert(item: LD[number], indexOrItem?: number | LD[number]): void;

The following is an example of returning to the first page and then inserting list items in non-append mode (page number flipping scenario):

page.value = 1;
nextTick(() => {
insert(newItem, 0);
});

The following is an example of scrolling to the top after inserting a list item in append mode (drop-down loading scene):

insert(newItem, 0);
nextTick(() => {
window.scrollTo(0, {});
});

You can also specify the second parameter of insert as a list item. When the same reference of this list item is found, the insert item will be inserted after this list item.

insert(newItem, afterItem);
Caution

In order to make the data correct, the insert function call will clear all caches.

Remove list item

In the case that the next page has a cache, it will use the cache of the next page to add to the end of the list item after removing an item, so as to ensure the same effect as re-requesting the data of the current page. In append mode and Behave the same in non-append mode.

/**
* Remove data
* If a list item is passed in, the list item will be removed, and an error will be thrown if the list item is not in the list data
* @param position index or list item to remove
*/
declare function remove(position: number | LD[number]): void;

You can also specify the second parameter of remove as a list item, and when the same reference of this list item is found, this list item will be removed.

But in the following two cases, it will re-initiate the request to refresh the data of the corresponding page:

  1. The next page is not cached
  2. The data that exceeds the next page cache list item is continuously called synchronously, and the cache data is not enough to supplement the current page list.
Caution

In order to make the data correct, the remove function call will clear all caches.

Update data items

Use this function when you want to update list items.

/**
* Replace data
* If the position passed in is a list item, this list item will be replaced, if the list item is not in the list data, an error will be thrown
* @param item replacement item
* @param position replacement position (index) or list item
*/
declare function replace(item: LD extends any[] ? LD[number] : any, position: number | LD[number]): void;

You can also specify the second parameter of replace as a list item, which will be replaced when an identical reference to the list item is found.

Refresh the data of the specified page

When you do not want to update the list items locally after the data operation, but re-request the data on the server side, you can use refresh to refresh the data on any page, without resetting the list data and letting the user start browsing from the first page again.

/**
* Refresh the specified page number data, this function will ignore the cache to force the send request
* If no page number is passed in, the current page will be refreshed
* If a list item is passed in, the page where the list item is located will be refreshed
* @param pageOrItemPage Refreshed page number or list item
*/
declare function refresh(pageOrItemPage?: number | LD[number]): void;

In append mode, you can specify the parameter of refresh as a list item. When the same reference of this list item is found, the data of the page number where this list item is located will be refreshed.

Manually update list data

Use the update function to update responsive data, which is similar to useRequest's update, the only difference is that when calling update to update data, the list data is updated, while non-response data. This is useful when manually clearing list data without reissuing the request.

// case list data
update({
data: []
});

Reset list

It will clear all caches and reload the first page.

/**
* Reload the list from the first page and clear the cache
*/
declare function reload(): void;

Limitation

Cache placeholder mode are temporarily disabled.

API

Hook configuration

Inherit all configurations of useWatcher.

NameDescriptionTypeDefaultVersion
initialPageinitial page numbernumber1-
initialPageSizeInitial number of data items per pagenumber10-
watchingStatesstate monitoring trigger request, implemented using useWatcherany[][page, pageSize]-
debounceThe debounce parameter of state monitoring, implemented by useWatchernumber | number[]--
appendWhether to enable append modebooleanfalse-
dataArray data specifying pagination(response: any) => any[]response => response.data-
totalspecify the total amount of data(response: any) => numberresponse => response.total-
preloadPreviousPagewhether to preload previous page databooleantrue-
preloadNextPagewhether to preload next page databooleantrue-

Responsive data

Inherit all responsive data from useWatcher.

NameDescriptionTypeVersion
pageCurrent page number, determined by initialPagenumber-
pageSizeThe current number of pages, determined by initialPageSizenumber-
datapaging list array data, obtained from data configurationany[]-
totalThe total amount of data, obtained from total configuration, can be emptynumber-
pageCountThe total number of pages, calculated from total and pageSizenumber-
isLastPageWhether the current page is the last page, if pageCount has a value, it will be obtained by comparing pageCount and page, otherwise it will be obtained by whether the length of the list data is less than pagSizenumber-
fetchingwhether data is being preloadedboolean-

Action function

Inherit all action functions of useWatcher.

namedescriptionfunction parametersreturn valueversion
refreshRefresh the data of the specified page number, this function will ignore the forced sending request of the cache, in the append mode, the list item can be passed in to indicate the page number where the list item is refreshedpageOrItemPage: Refreshed page number or list item--
insertInsert a piece of data. If no index is passed in, it will be inserted at the front by default. If a list item is passed in, it will be inserted after the list item. If the list item is not in the list data, an error will be thrown1. item: insert item
2. indexOrItem: insert position (index) or list item, default is 0
--
removeRemove a piece of data. When a number is passed in, it means the removed index. When the position is passed in a list item, the list item will be removed. If the list item is not in the list data, an error will be thrownposition : remove position (index) or list item--
replaceReplace a piece of data. When the second parameter is passed in a number, it means the replacement index. A negative number means counting from the end. When the position passed in is a list item, the list item will be replaced. If the list item is not in the list data An error will be thrown1. item: replacement item
2. position: replacement position (index) or list item, when a negative number is passed in, it means counting from the end
--
reloadClear the data and re-request the first page of data---
updateUpdate state data, same as alova's use hook, but update list data when updating data fieldnewFrontStates: new state data object--

Event

Inherit all events from useWatcher.

NameDescriptionCallback ParametersVersion
onFetchSuccessfetch success callback binding functionevent: alova success event object-
onFetchErrorcallback binding function for fetch failureevent: alova failure event object-
onFetchCompletecallback binding function for fetch completionevent: alova completion event object-