@hbis-uni/hbis-waterfall
v1.0.1
Published
HBIS UNI Waterfall Component
Keywords
Readme
HbisWaterfall 瀑布流组件
简介
HbisWaterfall 是一个基于 Vue 3 开发的瀑布流布局组件,支持动态列数、动态数据加载、高度计算和自定义内容。适用于图片展示、商品列表等需要瀑布流布局的场景。
特性
- 动态列数:支持 2 到 maxColumn 列的动态调整
- 高度计算:根据组件宽度和图片比例计算高度,实现真正的瀑布流效果
- 响应式布局:使用组件宽度而非屏幕宽度,适应不同容器大小
- 自定义内容:通过插槽支持自定义图片下方的内容
- 实时调整:支持通过滑块等控件实时调整列数和间距
- 性能优化:只在必要时重新计算和分配数据
- 错误处理:包含图片加载错误处理
安装
作为组件库的一部分安装
pnpm add @hbis-uni/components单独安装
pnpm add @hbis-uni/hbis-waterfall使用方法
基本使用
<template>
<HbisWaterfall
:data="waterfallData"
:column="2"
:max-column="5"
:column-gap="10"
:row-gap="10"
image-key="url"
item-key="id"
/>
</template>
<script setup>
import { HbisWaterfall } from '@hbis-uni/components';
const waterfallData = [
{
id: 'img-1',
url: 'https://example.com/image1.jpg'
},
{
id: 'img-2',
url: 'https://example.com/image2.jpg'
},
// 更多数据...
];
</script>带自定义内容的使用
<template>
<HbisWaterfall
ref="waterfallRef"
:data="waterfallData"
:column="3"
:column-gap="15"
:row-gap="15"
image-key="url"
item-key="id"
>
<template #default="{ item, index }">
<div class="custom-content">
<h3>图片 {{ index + 1 }}</h3>
<p>描述: {{ item.description || '无描述' }}</p>
</div>
</template>
</HbisWaterfall>
</template>
<script setup>
import { ref } from 'vue';
import { HbisWaterfall } from '@hbis-uni/components';
const waterfallRef = ref();
const waterfallData = [
{
id: 'img-1',
url: 'https://example.com/image1.jpg',
description: '这是一张测试图片'
},
// 更多数据...
];
// 手动刷新瀑布流
const refreshWaterfall = () => {
waterfallRef.value?.refresh();
};
</script>
<style scoped>
.custom-content {
padding: 15px;
background-color: white;
border-radius: 0 0 8px 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
</style>API
属性
| 属性名 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| data | Array | [] | 瀑布流数据数组,每个元素应包含图片URL等信息 |
| column | Number | 2 | 列数,最小为2 |
| maxColumn | Number | 5 | 最大列数 |
| columnGap | [Number, String] | 10 | 列间距(px) |
| rowGap | [Number, String] | 10 | 行间距(px) |
| itemKey | String | 'id' | 数据唯一键字段名 |
| imageKey | String | 'url' | 图片URL字段名 |
事件
| 事件名 | 说明 | 参数 |
| --- | --- | --- |
| load | 图片加载成功事件 | event: Event |
| error | 图片加载失败事件 | event: Event |
插槽
| 插槽名 | 说明 | 作用域变量 |
| --- | --- | --- |
| default | 自定义内容插槽,用于展示图片下方的内容 | { item: Object, index: Number } |
方法
| 方法名 | 说明 | 参数 | 返回值 | | --- | --- | --- | --- | | refresh | 刷新数据,重新分配到多列 | 无 | 无 |
数据结构
基本数据结构
const waterfallData = [
{
id: 'img-1', // 唯一标识,对应 itemKey
url: 'https://example.com/image1.jpg', // 图片URL,对应 imageKey
description: '图片描述' // 自定义字段,可在插槽中使用
},
// 更多数据...
];字段说明
id:数据唯一键,用于 Vue 的 v-for 渲染,可通过itemKey属性指定其他字段url:图片URL,用于显示图片,可通过imageKey属性指定其他字段- 其他字段:可自定义添加,在插槽中通过
item访问
示例
完整示例
<template>
<div class="waterfall-demo">
<h2>瀑布流组件示例</h2>
<div class="controls">
<div class="control-group">
<label>列数: {{ column }}</label>
<input
type="range"
v-model.number="column"
min="2"
:max="maxColumn"
step="1"
/>
</div>
<div class="control-group">
<label>列间距: {{ columnGap }}px</label>
<input
type="range"
v-model.number="columnGap"
min="0"
max="30"
step="1"
/>
</div>
<div class="control-group">
<label>行间距: {{ rowGap }}px</label>
<input
type="range"
v-model.number="rowGap"
min="0"
max="30"
step="1"
/>
</div>
<button @click="addMoreData">加载更多</button>
</div>
<HbisWaterfall
ref="waterfallRef"
:data="waterfallData"
:column="column"
:max-column="maxColumn"
:column-gap="columnGap"
:row-gap="rowGap"
image-key="url"
item-key="id"
@load="handleImageLoad"
@error="handleImageError"
>
<template #default="{ item, index }">
<div class="custom-content">
<h3>图片 {{ index + 1 }}</h3>
<p>描述: {{ item.description }}</p>
<p>尺寸: {{ item.width }} × {{ item.height }}</p>
</div>
</template>
</HbisWaterfall>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { HbisWaterfall } from '@hbis-uni/components';
const waterfallRef = ref();
const column = ref(2);
const maxColumn = ref(5);
const columnGap = ref(10);
const rowGap = ref(10);
const waterfallData = ref([]);
// 生成测试数据
const generateTestData = (count = 20) => {
const data = [];
const widths = [200, 250, 300, 350, 400];
for (let i = 0; i < count; i++) {
const width = widths[Math.floor(Math.random() * widths.length)];
const height = Math.floor(width * (0.5 + Math.random()));
data.push({
id: `img-${Date.now()}-${i}`,
url: `https://gips1.baidu.com/it/u=3874647369,3220417986&fm=3028&app=3028&f=JPEG&fmt=auto?w=720&h=1280`,
description: `这是第 ${i + 1} 张测试图片`,
width,
height
});
}
return data;
};
// 加载更多数据
const addMoreData = () => {
const newData = generateTestData(10);
waterfallData.value = [...waterfallData.value, ...newData];
};
// 处理图片加载
const handleImageLoad = (event) => {
console.log('图片加载成功:', event.target.src);
};
// 处理图片错误
const handleImageError = (event) => {
console.error('图片加载失败:', event.target.src);
};
// 组件挂载
onMounted(() => {
waterfallData.value = generateTestData(20);
});
</script>
<style scoped>
.waterfall-demo {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.controls {
background-color: #f5f5f5;
padding: 20px;
border-radius: 8px;
margin-bottom: 20px;
}
.control-group {
margin-bottom: 15px;
display: flex;
align-items: center;
gap: 10px;
}
.control-group label {
width: 120px;
font-weight: bold;
}
.control-group input[type="range"] {
flex: 1;
}
button {
padding: 10px 20px;
background-color: #409eff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #66b1ff;
}
.custom-content {
padding: 15px;
background-color: white;
border-radius: 0 0 8px 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.custom-content h3 {
margin: 0 0 10px 0;
color: #333;
font-size: 16px;
}
.custom-content p {
margin: 5px 0;
color: #666;
font-size: 14px;
}
</style>注意事项
数据项要求:
- 数据项必须包含唯一键(通过 itemKey 指定),用于 Vue 的 v-for 渲染
- 数据项必须包含图片 URL(通过 imageKey 指定),用于显示图片
性能优化:
- 当数据量较大时,建议使用虚拟滚动或分页加载
- 图片建议使用适当的尺寸,避免过大的图片影响加载性能
布局注意事项:
- 组件容器应设置适当的宽度,以便组件能够正确计算列宽
- 当容器宽度变化时,组件会自动重新计算布局
兼容性:
- 支持 Vue 3 项目和 Uniapp 项目
- 在 Uniapp 中使用时,注意平台差异(如样式前缀等)
浏览器兼容性
- Chrome >= 60
- Firefox >= 55
- Safari >= 12
- Edge >= 79
- 支持现代移动浏览器
贡献
欢迎提交 Issue 和 Pull Request 来改进这个组件。
许可证
ISC
