虚拟列表 + 瀑布流
效果
属性
参数 |
说明 |
类型 |
可选值 |
默认值 |
size |
一次性添加的数据条数 |
number |
- |
50 |
column |
列数 |
number |
- |
1 |
marginBottom |
每项底边距 |
number |
- |
0 |
loading |
数据加载状态 |
boolean |
- |
false |
marginTop |
距离底部多少开始拉取数据 |
number |
- |
1000 |
data |
需要进行分裂的数据,{height:300},一定要含有高度字段,防止加载图片文件缓慢计算不准确 |
array |
- |
{height:300} |
方法
事件名称 |
说明 |
回调参数 |
fetchData |
滚动到指定位置通知加载数据 |
- |
组件内容
<template>
<div class="c-virtual-list">
<!-- 一屏内容有高度 -->
<div
class="virtual-screen"
v-for="(screen, index) in list"
:key="index"
:data-index="index"
:style="{ height: screen.height + 'px' }"
>
<!-- 通过v-if进行判断 节点交互是否出现在当前视口内 -->
<div class="screen-content" v-if="computeShow(index)">
<!-- 渲染列数 -->
<div
class="column"
v-for="(column, cIndex) in screen.columns"
:key="cIndex"
:style="{
marginTop:
index > 0 ? `-${
list[index - 1].heightOffset[cIndex]}px` : '0',
}"
>
<slot :data="column" :index="index"></slot>
<!-- 插槽向外部暴露数据 -->
</div>
</div>
</div>
<div class="loading" :style="{ marginTop: -marginTop + 'px' }">loading</div>
</div>
</template>
<script setup>
import {
defineProps,
defineEmits,
nextTick,
onBeforeUnmount,
onMounted,
reactive,
watch,
} from "vue";
const props = defineProps({
size: {
type: Number,
require: true,
default: 50,
},
column: {
type: Number,
default: 1,
},
marginBottom: {
type: Number,
default: 0,
},
loading: {
type: Boolean,
default: false,
},
marginTop: {
type: Number,
default: 1000,
},
data: {
type: Array,
default: () => [],
},
});
const list = reactive([
]);
const item = {
height: 300,
color: "",
};
const showList = reactive([-1, 0, 1]);
const emits = defineEmits(["update:loading", "fetchData"]);
onMounted(() => {
createNodeObserve(".loading", () => {
console.log("去加载数据");
emits("fetchData");
});
});
watch(props.data, (newData, preDate) => {
divisionData(newData);
nextTick(() => {
createNodeObserve(".virtual-screen", (index) => {
Object.assign(showList, [index - 1, index, index + 1]);
});
});
});
let ob;
const