# List 虚拟列表 
大数据时候用的列表,数据大于 400
# 基础用法
<template>
<div>
<qinui-list
ref="thePageNode"
use-virtual-list
idPrefix="store-id"
:force-close-inner-list="true"
@virtualListChange="onVirtualListChange"
@query="onGetDatas"
>
<!-- 需要固定在顶部不滚动的view放在slot="top"的view中,如果需要跟着滚动,则不要设置slot="top" -->
<template #top>
<view class="header">列表总数据量:10万条</view>
<!-- 注意!此处的z-tabs为独立的组件,可替换为第三方的tabs,若需要使用z-tabs,请在插件市场搜索z-tabs并引入,否则会报插件找不到的错误 -->
<qinui-tabs
:data="theTabList"
@change="onTabsChange"
v-model="theTabIndex"
/>
</template>
<!-- :id="`store-id-${item.zp_index}`"和:key="item.zp_index" 必须写,必须写!!!! -->
<!-- store-id 和 idPrefix 一致-->
<!-- 这里for循环的index不是数组中真实的index了,请使用item.zp_index获取真实的index -->
<view
class="item"
:id="`store-id-${item.zp_index}`"
:key="item.zp_index"
v-for="(item, index) in theDataList"
>
<image
class="item-image"
mode="aspectFit"
src="https://cdn.test.fanzhi.cn//images/0d/d2/70d5dc70ce6f898142cc288cf52c.jpg?x-oss-process=image/resize,w_288,h_393,m_fill/quality,q_100"
></image>
<view class="item-content">
<text class="item-title">第{{ item.title }}行</text>
<text style="color: red; margin-left: 10rpx">虚拟列表展示</text>
<view class="item-detail">{{ item.detail }}</view>
</view>
<view class="item-line"></view>
</view>
</qinui-list>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import theAjax from '../list/ajax';
// 虚拟列表节点
const thePageNode = ref<any>(null);
// tab start
const theTabIndex = ref('tab1');
const theTabList = ref([
{
label: '测试1',
value: 'tab1',
},
{
label: '测试2',
value: 'tab2',
},
{
label: '测试3',
value: 'tab3',
},
{
label: '测试4',
value: 'tab4',
},
]);
const onTabsChange = () => {
// 当切换tab或搜索时请调用组件的reload方法,请勿直接调用:queryList方法!!
thePageNode.value?.reload();
};
// tab end
// 虚拟列表数据 start
const theDataList = ref<any>([]);
// 监听虚拟列表数组改变并赋值给virtualList进行重新渲染
const onVirtualListChange = (vList: any) => {
theDataList.value = vList;
};
const onGetDatas = (thePageNo: number, thePageSize: number) => {
// 组件加载时会自动触发此方法,因此默认页面加载时会自动触发,无需手动调用
// 这里的 thePageNo 和 thePageSize 会自动计算好,直接传给服务器即可
// 模拟请求服务器获取分页数据,请替换成自己的网络请求
const theParams = {
pageNo: thePageNo,
pageSize: thePageSize,
type: theTabIndex.value,
};
theAjax
.queryListLong(theParams)
.then((theRes: any) => {
// 将请求的结果数组传递给 qinui-list
thePageNode.value.complete(theRes.data.list);
})
.catch(() => {
// 如果请求失败写 thePageNode.value.complete(false);
// 注意,每次都需要在catch中写这句话很麻烦, qinui-list 提供了方案可以全局统一处理
// 在底层的网络请求抛出异常时,写 qin.$emit('qinui-list-error-emit'); 即可
thePageNode.value.complete(false);
});
};
// 虚拟列表数据 end
</script>
<style>
/* 示例样式 start */
.item {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 30rpx;
}
.item-content {
flex: 1;
margin-left: 20rpx;
}
.header {
background-color: red;
font-size: 24rpx;
text-align: center;
padding: 20rpx 0rpx;
color: white;
}
.item-image {
height: 150rpx;
width: 150rpx;
background-color: #eeeeee;
border-radius: 10rpx;
}
.item-title {
background-color: red;
color: white;
font-size: 26rpx;
border-radius: 5rpx;
padding: 5rpx 10rpx;
}
.item-detail {
margin-top: 10rpx;
border-radius: 10rpx;
font-size: 28rpx;
color: #aaaaaa;
word-break: break-all;
}
.item-line {
position: absolute;
bottom: 0rpx;
left: 0rpx;
height: 1px;
width: 100%;
background-color: #eeeeee;
}
/* 示例样式 end */
</style>
# 悬停用法
<template>
<div>
<qinui-list
ref="thePageNode"
use-virtual-list
:force-close-inner-list="true"
@virtualListChange="onVirtualListChange"
@query="onGetDatas"
>
<view class="banner-view" style="height: 250rpx">
<view style="font-size: 40rpx; font-weight: 700">这是一个banner</view>
<view style="font-size: 24rpx; margin-top: 5rpx"
>下方tab滚动时可吸附在顶部</view
>
</view>
<qinui-affix>
<qinui-tabs
:data="theTabList"
@change="onTabsChange"
v-model="theTabIndex"
/>
</qinui-affix>
<!-- :id="`zp-id-${item.zp_index}`"和:key="item.zp_index" 必须写,必须写!!!! -->
<!-- 这里for循环的index不是数组中真实的index了,请使用item.zp_index获取真实的index -->
<view
class="item"
:id="`zp-id-${item.zp_index}`"
:key="item.zp_index"
v-for="(item, index) in theDataList"
>
<image
class="item-image"
mode="aspectFit"
src="https://cdn.test.fanzhi.cn//images/0d/d2/70d5dc70ce6f898142cc288cf52c.jpg?x-oss-process=image/resize,w_288,h_393,m_fill/quality,q_100"
></image>
<view class="item-content">
<text class="item-title">第{{ item.title }}行</text>
<text style="color: red; margin-left: 10rpx">虚拟列表展示</text>
<view class="item-detail">{{ item.detail }}</view>
</view>
<view class="item-line"></view>
</view>
</qinui-list>
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import theAjax from '../list/ajax';
// 虚拟列表节点
const thePageNode = ref<any>(null);
// tab start
const theTabIndex = ref('tab1');
const theTabList = ref([
{
label: '测试1',
value: 'tab1',
},
{
label: '测试2',
value: 'tab2',
},
{
label: '测试3',
value: 'tab3',
},
{
label: '测试4',
value: 'tab4',
},
]);
const onTabsChange = () => {
// 当切换tab或搜索时请调用组件的reload方法,请勿直接调用:queryList方法!!
thePageNode.value?.reload();
};
// tab end
// 虚拟列表数据 start
const theDataList = ref<any>([]);
// 监听虚拟列表数组改变并赋值给virtualList进行重新渲染
const onVirtualListChange = (vList: any) => {
theDataList.value = vList;
};
const onGetDatas = (thePageNo: number, thePageSize: number) => {
// 组件加载时会自动触发此方法,因此默认页面加载时会自动触发,无需手动调用
// 这里的 thePageNo 和 thePageSize 会自动计算好,直接传给服务器即可
// 模拟请求服务器获取分页数据,请替换成自己的网络请求
const theParams = {
pageNo: thePageNo,
pageSize: thePageSize,
type: theTabIndex.value,
};
theAjax
.queryListLong(theParams)
.then((theRes: any) => {
// 将请求的结果数组传递给 qinui-list
thePageNode.value.complete(theRes.data.list);
})
.catch(() => {
// 如果请求失败写 thePageNode.value.complete(false);
// 注意,每次都需要在catch中写这句话很麻烦, qinui-list 提供了方案可以全局统一处理
// 在底层的网络请求抛出异常时,写 qin.$emit('qinui-list-error-emit'); 即可
thePageNode.value.complete(false);
});
};
// 虚拟列表数据 end
</script>
<style>
/* 示例样式 start */
.banner-view {
background-color: #007aff;
color: white;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.item {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 30rpx;
}
.item-content {
flex: 1;
margin-left: 20rpx;
}
.header {
background-color: red;
font-size: 24rpx;
text-align: center;
padding: 20rpx 0rpx;
color: white;
}
.item-image {
height: 150rpx;
width: 150rpx;
background-color: #eeeeee;
border-radius: 10rpx;
}
.item-title {
background-color: red;
color: white;
font-size: 26rpx;
border-radius: 5rpx;
padding: 5rpx 10rpx;
}
.item-detail {
margin-top: 10rpx;
border-radius: 10rpx;
font-size: 28rpx;
color: #aaaaaa;
word-break: break-all;
}
.item-line {
position: absolute;
bottom: 0rpx;
left: 0rpx;
height: 1px;
width: 100%;
background-color: #eeeeee;
}
/* 示例样式 end */
</style>
# API
# Props
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|---|---|---|---|---|
| use-virtual-list | 是否使用虚拟列表 | Boolean | false | true | false |
| force-close-inner-list | 强制关闭inner-list,默认为false,如果为true将强制关闭innerList,适用于开启了虚拟列表后需要强制关闭inner-list的情况 | Boolean | false | true | false |
| idPrefix | id 前缀 | String | zp-id | - |
| fixed | 默认配置,z-paging为position: fixed并铺满整个页面,脱离页面文档流。z-paging标签外的view都会被它盖住或盖住它。建议:页面中所有元素写在z-paging标签内(包括自定义的导航栏或者自定义的tabbar),如果需要固定在顶部的则放在slot="top"中,固定在底部的放在slot="bottom",此时z-paging是局部滚动的。 | |||
| 适用场景:一般的页面列表分页 | Boolean | true | - | |
| fixed-cell-height | 当 fixed="false" 的时候必须指定每条的高度 | String | Number | - | - |
| height | 当 fixed="false" 的时候必须指定整个列表的高度 | String | Number | - | - |
| hideEmptyView | 是否隐藏空状态展示 | Boolean | false | - |
# Events
| 事件名 | 说明 | 回调参数 |
|---|---|---|
| @scroll | 页面滚动的监听事件 | 滚动数据 |
| @virtualListChange | 虚拟列表当前渲染的数组改变时触发,在虚拟列表中只会渲染可见区域内+预加载页面的数据 | 虚拟列表当前渲染的数组 |
| @query | 下拉刷新或滚动到底部时会自动触发此方法。 qiniu-list 加载时也会触发(若要禁止,请设置:auto="false")。pageNo和pageSize会自动计算好,直接传给服务器即可。 | 参数1:pageNo(当前第几页);参数2:pageSize(每页多少条)(pageSize必须与传给服务器的一致,如果需要修改pageSize,请通过:default-page-size="15"修改)参数3 :from(@query的触发来源:0.用户主动下拉刷新 1.通过reload触发 2.通过refresh触发 3.通过滚动到底部加载更多或点击底部加载更多触发) |