更新记录
1.0.3(2026-09-02)
下载此版本
重构
1.0.2(2024-11-20)
下载此版本
- 优化dom问题判断
1.0.1(2024-11-18)
下载此版本
- 优化
| 属性 |
说明 |
类型 |
默认值 |
可选值 |
| backTopShow |
返回顶部 |
Boolean |
true |
true/false |
| scrollwithanimation |
scroll-view (scroll-with-animation) |
Boolean |
true |
true/false |
| isnextpage |
是否已是最后一页 |
Boolean |
false |
true/false |
| imgSrc |
列表中图片字段 |
String |
src (与列表中图片字段对应) |
--- |
| 方法 |
说明 |
接收值 |
| backTop |
返回顶部 (使用ref方式调用) |
val (true 初始化数据) |
| Init |
数据处理渲染(使用ref方式调用) |
arr (列表包含图片) |
| scroll |
滚动事件 |
scrollTop (当前滚动的距离) |
| scrolltolower |
触底事件 |
--- |
| 插槽 |
说明 |
接收值 |
| top |
列表上方的内容 |
--- |
| bottom |
列表下方的内容 |
--- |
| Backtotop |
自定义返回顶部样式 |
--- |
| left |
列表左侧循环渲染的内容 |
item |
| right |
列表右侧循环渲染的内容 |
item |
查看更多
平台兼容性
uni-app
| Vue2 |
Vue3 |
Chrome |
Safari |
app-vue |
app-nvue |
Android |
iOS |
鸿蒙 |
| √ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
| 微信小程序 |
支付宝小程序 |
抖音小程序 |
百度小程序 |
快手小程序 |
京东小程序 |
鸿蒙元服务 |
QQ小程序 |
飞书小程序 |
小红书小程序 |
快应用-华为 |
快应用-联盟 |
| √ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
√ |
其他
SL-Waterfall 瀑布流组件
适用于 uni-app(H5 / 各端小程序)的瀑布流组件。支持网络图片(无需预知宽高)、多列布局、左列不低于右列、渐进渲染、触底加载、返回顶部、空状态。
特性
-
网络图片自适应:通过 <image> 的 @load 事件获取真实宽高,无需 uni.getImageInfo,规避 H5 跨域与小程序域名白名单问题
-
多列布局:可配置列数、列间距、行间距
-
左列不低于右列:分配后做批末修正,保证累计高度非递增,避免右列空白
-
渐进渲染:已渲染的 item 永不删除,滚动时无抖动;DOM 量随用户浏览量增长,可控
-
组件内滚动:基于 scroll-view,不依赖页面级生命周期,触底/返回顶部均由组件自身实现
-
H5 / 小程序通用:无平台特有 API 依赖
字段说明(Props)
| 字段 |
类型 |
默认值 |
说明 |
list |
Array |
[] |
数据源数组,每项需包含图片地址字段 |
columnCount |
Number |
2 |
列数 |
imageKey |
String |
'image' |
数据项中图片地址的字段名 |
columnGap |
Number |
16 |
列间距(rpx) |
rowGap |
Number |
16 |
行间距(rpx) |
padding |
Number |
16 |
外层内边距(rpx) |
leftHigher |
Boolean |
true |
是否保证左列累计高度不低于右列 |
height |
String |
'100vh' |
scroll-view 高度(CSS 值,必须为确定值才能滚动) |
enableVirtual |
Boolean |
true |
是否启用渐进渲染(关闭则全量渲染) |
virtualBuffer |
Number |
600 |
渐进渲染缓冲区(px),距底部还剩这么多时提前渲染下一批 |
renderStep |
Number |
6 |
每次渐进渲染增加的 item 数量 |
lowerThreshold |
Number |
80 |
触底距离(px) |
backTopThreshold |
Number |
600 |
显示返回顶部按钮的滚动阈值(px) |
事件说明(Events)
| 事件名 |
回调参数 |
说明 |
itemtap |
item |
点击某个 item 时触发,返回该 item 数据 |
scrolltolower |
无 |
滚动触底时触发,用于加载更多 |
scroll |
{ scrollTop } |
滚动时触发,返回当前滚动位置(节流 80ms) |
backtopchange |
{ show } |
返回顶部按钮显隐变化时触发 |
方法说明(通过 ref 调用)
| 方法名 |
参数 |
说明 |
scrollToTop |
duration = 300 |
平滑滚动回顶部 |
this.$refs.waterfall.scrollToTop();
插槽说明(Slots)
| 插槽名 |
作用域参数 |
说明 |
item |
item |
单个 item 底部内容(文案等),默认显示 item.title |
footer |
无 |
scroll-view 内部底部,常用于加载状态 |
backtop |
无 |
返回顶部按钮自定义样式,默认圆形半透明黑底 + ↑ |
empty |
无 |
空数据状态自定义样式,默认居中"暂无数据" |
示例
基础用法
<template>
<sl-waterfall
:list="list"
:column-count="2"
image-key="image"
@itemtap="onItemTap"
@scrolltolower="loadMore"
/>
</template>
<script>
export default {
data() {
return { list: [] };
},
methods: {
loadMore() {
// 追加数据到 this.list
},
onItemTap(item) {
uni.showToast({ title: item.title, icon: 'none' });
}
}
};
</script>
完整示例(自定义插槽 + 触底加载 + 返回顶部 + 空状态)
<template>
<view class="page">
<sl-waterfall
ref="waterfall"
:list="list"
:column-count="2"
:column-gap="16"
:row-gap="16"
:padding="16"
height="100vh"
:enable-virtual="true"
:lower-threshold="80"
:back-top-threshold="600"
image-key="image"
@itemtap="onItemTap"
@scrolltolower="loadMore"
>
<!-- 自定义 item 底部内容 -->
<template v-slot:item="{ item }">
<view class="card-footer">
<text class="card-title">{{ item.title }}</text>
<text class="card-author">{{ item.author }}</text>
</view>
</template>
<!-- 自定义返回顶部按钮 -->
<template v-slot:backtop>
<view class="custom-backtop">
<text>顶部</text>
</view>
</template>
<!-- 自定义空数据 -->
<template v-slot:empty>
<view class="custom-empty">
<text>📭 还没有内容</text>
</view>
</template>
<!-- 触底加载状态 -->
<template v-slot:footer>
<view class="load-more">
<text v-if="loading">加载中…</text>
<text v-else-if="noMore">没有更多了</text>
</view>
</template>
</sl-waterfall>
</view>
</template>
<script>
export default {
data() {
return {
list: [],
page: 1,
loading: false,
noMore: false
};
},
onLoad() {
this.loadMore();
},
methods: {
loadMore() {
if (this.loading || this.noMore) return;
this.loading = true;
// 模拟请求
const next = [];
for (let i = 0; i < 8; i++) {
const seed = (this.page - 1) * 8 + i + 1;
next.push({
image: `https://picsum.photos/seed/${seed}/400/${300 + (seed % 5) * 80}`,
title: '标题' + seed,
author: '作者'
});
}
setTimeout(() => {
this.list = this.list.concat(next);
this.page++;
this.loading = false;
}, 300);
},
onItemTap(item) {
uni.showToast({ title: item.title, icon: 'none' });
}
}
};
</script>
多列布局
<sl-waterfall :list="list" :column-count="3" :column-gap="12" :row-gap="12" />
关闭渐进渲染(数据量小时)
<sl-waterfall :list="list" :enable-virtual="false" />
调用返回顶部
<sl-waterfall ref="waterfall" :list="list" />
<script>
export default {
methods: {
backToTop() {
this.$refs.waterfall.scrollToTop();
}
}
};
</script>
注意事项
- 小程序图片域名:网络图片需在 小程序后台 → 开发管理 → 服务器域名 加入合法域名(开发期可在开发者工具勾选「不校验合法域名」);H5 无此限制。
-
easycom 配置:若目录结构为 components/SL-WX-Compent-Waterfall/index.vue(目录名与文件名不一致),需在 pages.json 配置自定义 easycom 规则:
"easycom": {
"custom": {
"^sl-waterfall": "@/components/SL-WX-Compent-Waterfall/index.vue"
}
}
- height 必须为确定值:scroll-view 需明确高度才能滚动,如
100vh、600rpx,不能用 auto。
- 渐进渲染与虚拟列表区别:本组件用渐进渲染(已渲染永不删除),滚动时无 DOM 删除 → 无抖动,DOM 量随浏览量增长。如需固定 DOM 数量可自行改为虚拟列表方案。