uniapp瀑布列表

uniapp瀑布列表我看了下好像没什么好用的插件,或者都是一些计算麻烦的,还有就是样式做的定位不太好分页。所以自己写了一个,比较简单,支持做分页。设定几列,我就添加几个数组,然后给高度最短的列push数据。最核心的代码也就那么几行,反正挺简单,代码里都有注释,直接整个粘贴过去看效果

<template>
  <view class="list">
    <view class="list-column" v-for="(item, index) in list" :key="index">
      <!-- 这个盒子一定要,计算每列总高度的 -->
      <view :class="'column' + index">
        <view class="detail" v-for="(item1, i) in item" :key="i">
          <image :src="item1.img"></image>
          <view>{{ item1.title }}</view>
        </view>
      </view>
    </view>
  </view>
</template>
<script>
export default {
  data() {
    return {
      column: 3, //列数需大于0,可随意切换
      list: [], //数据列表
      heightList: [], //保存每列的高度
      timer: null, //定时器需要延时获取dom高度
    };
  },
  async onLoad() {
    await this.getColumnList();
    await this.getList();
  },
  onUnload() {
    clearInterval(this.timer);
  },
  onReachBottom() {
	// 分页逻辑按照自己需求写
	this.getList()
  },
  methods: {
    // 初始化数组的列数,添加空数组
    getColumnList() {
      this.list = [];
      for (let i = 0; i < this.column; i++) {
        this.list.push([]);
      }
    },
    // 获取接口数据
    getList() {
      // 假如这里是接口获取的数组
      let data = [
        {
          img: "https://t8.baidu.com/it/u=3272525572,1712724531&fm=3035&app=3035&size=f242,150&n=0&f=JPEG&fmt=auto?s=B39CA76E7560451B980B337E0300D07C&sec=1729184400&t=de3a34366e8f44e2c1544e1bd92f1474",
          title: "标题标题标题标题标题标题标题标题标题标题标题标题标题标题",
        },
        {
          img: "https://t8.baidu.com/it/u=3897666234,2873419740&fm=217&app=126&size=f242,150&n=0&f=JPEG&fmt=auto?s=AE62C214FE226B03460E5FD80300B0BF&sec=1729184400&t=0baba2ab4af4b3a863f311d5cbf8895f",
          title: "标题题标题",
        },
        {
          img: "https://t7.baidu.com/it/u=3257192411,2459472063&fm=217&app=126&size=f242,150&n=0&f=JPEG&fmt=auto?s=24AC60B4DC422ED626181D09030060D3&sec=1729184400&t=ce9d5b84064de942e7144fcce84a177a",
          title: "标标题标标题标标题标标题",
        },
        {
          img: "https://t7.baidu.com/it/u=3562468818,2226789446&fm=3031&app=3031&size=f242,150&n=0&f=JPEG&fmt=auto?s=40125F98770451E74A04DC50030070F1&sec=1729184400&t=8d26ee442dab4e4e29706cbb972d1ef3",
          title: "标题标题标题题标题标题标题标题标题",
        },
        {
          img: "https://t9.baidu.com/it/u=3270408099,2255924736&fm=3031&app=3031&size=f242,150&n=0&f=JPEG&fmt=auto?s=73BF27660F80496242CFE37B0300E07A&sec=1729184400&t=198738e9dda29c2d3024af117802a080",
          title: "标题标题标题标题标题标题标题标题标题标题标题标题标题标题",
        },
        {
          img: "https://t9.baidu.com/it/u=922375208,550964998&fm=3031&app=3031&size=f242,150&n=0&f=JPEG&fmt=auto?s=E192EF3E8BCF444B5AD7C0C7020020BB&sec=1729184400&t=caa743d6e8acac9462dee574cd8239a1",
          title: "标题标题标题标题标题标题标题标题",
        },
        {
          img: "https://t8.baidu.com/it/u=3272525572,1712724531&fm=3035&app=3035&size=f242,150&n=0&f=JPEG&fmt=auto?s=B39CA76E7560451B980B337E0300D07C&sec=1729184400&t=de3a34366e8f44e2c1544e1bd92f1474",
          title: "标题标题标题标题标题标题标题标题标题标题标题标题标题标题",
        },
        {
          img: "https://t8.baidu.com/it/u=3897666234,2873419740&fm=217&app=126&size=f242,150&n=0&f=JPEG&fmt=auto?s=AE62C214FE226B03460E5FD80300B0BF&sec=1729184400&t=0baba2ab4af4b3a863f311d5cbf8895f",
          title: "标题题标题标题标题标题",
        }
      ];
      //接口拿到数据后开始逐步渲染
      if (data && data.length) {
        for (let i = 0; i < data.length; i++) {
          this.timer = setTimeout(() => {
            this.getDom(data[i]); //将单个数据添加到各个列中
          }, i * 20); //这个20毫秒延迟可以改大看尾部添加的效果
        }
      }
    },
    // 获取哪一列的高度最小
    getDom(i) {
      this.heightList = [];
      const query = uni.createSelectorQuery().in(this);
      this.list.forEach((i, index) => {
        query
          .select(`.column${index}`)
          .boundingClientRect((data) => {
            this.heightList.push({ index, height: data.height }); //获取每一列dom的高度
            this.heightList = Array.from(
              new Set(this.heightList.map(JSON.stringify))
            ).map(JSON.parse);
          })
          .exec();
      });
      let min = Math.min(...this.heightList.map((obj) => obj.height)); //几列中对比哪个最小
      let minValue = this.heightList.findIndex((j) => j.height == min);
      this.list[minValue].push(i); //将列高度最小的,添加单条数据到对应的数组
    }
  }
};
</script>

<style>
.list {
  display: flex;
  padding: 32rpx;
}
.list-column {
  flex: 1;
  margin-right: 32rpx;
}
.list-column:last-child {
  margin-right: 0;
}
.detail {
  margin-bottom: 32rpx;
}
.detail image {
  width: 100%;
}
</style>

总结:就是获取dom比较大小,然后获取dom需要一点点的延迟。要是vue的项目可以改改获取dom高度的方法应该就可以使用了

### 实现 UniApp 瀑布列表UniApp 中实现瀑布布局可以通过自定义组件来完成。下面是一个详细的教程以及相应的代码示例。 #### 创建瀑布组件 创建一个新的 Vue 组件 `waterfall-flow.vue` 来作为瀑布容器: ```vue <template> <view class="waterfall-container"> <view v-for="(item, index) in list" :key="index" :class="'column-' + (index % 2)"> <!-- 这里放置具体的 item --> {{ item }} </view> </view> </template> <script> export default { props: ['list'], methods: { clear() { this.$emit('clear'); }, update() { this.$emit('update'); } } } </script> <style scoped> .waterfall-container { display: flex; } .column-0, .column-1 { width: 50%; padding: 5px; box-sizing: border-box; } </style> ``` 此模板中的每一项会交替分配到两列中,形成简单的双栏瀑布效果[^1]。 #### 使用瀑布组件 在页面文件中引入并注册该组件,在父级视图中使用它,并处理数据加载逻辑: ```html <template> <view> <waterfall-flow ref="myWaterfallFlow" :list="items"></waterfall-flow> </view> </template> <script> import WaterfallFlow from '@/components/waterfall-flow'; export default { components: { WaterfallFlow }, data() { return { items: [] }; }, onLoad() { this.getItems(); }, onPullDownRefresh() { this.items = []; this.$refs.myWaterfallFlow.clear(); setTimeout(() => { this.getItems(); uni.stopPullDownRefresh(); }, 500); }, methods: { getItems() { // 模拟获取远程数据的过程 const mockData = Array.from({ length: 10 }).map((_, i) => 'Item ' + i); this.items.push(...mockData); } } }; </script> ``` 这段脚本展示了如何初始化瀑布组件、监听下拉刷新事件并更新显示的数据集合。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值