当前位置: 首页 > news >正文

小程序实现瀑布流布局

小程序瀑布流

基于vue3的小程序瀑布流

<template>
  <view class="u-waterfall">
    <view id="u-left-column" class="u-column"
      ><slot name="left" :left-list="leftList"></slot
    ></view>
    <view id="u-right-column" class="u-column">
      <slot name="right" :right-list="rightList"></slot>
    </view>
  </view>
</template>

<script setup lang="ts">
import { ref, watch, getCurrentInstance } from "vue";
const props = defineProps({
  flowList: {
    type: Array,
    default: () => [],
  },
  // 每次向结构插入数据的时间间隔,间隔越长,越能保证两列高度相近,但是对用户体验越不好
  addTime: {
    type: Number,
    default: 250,
  },
});
const leftList = ref([]);
const rightList = ref([]);
const tempList = ref([]);
const instance = getCurrentInstance();
const uGetRect = (id: string) => {
  return new Promise((resolve, reject) => {
    const query = uni.createSelectorQuery().in(instance);
    query
      .select(id)
      .boundingClientRect((data) => {
        resolve(data);
      })
      .exec();
  });
};
const splitData = async () => {
  if (!tempList.value.length) {
    return;
  }
  const leftRect: any = await uGetRect("#u-left-column");
  const rightRect: any = await uGetRect("#u-right-column");
  // 如果左边小于或等于右边,就添加到左边,否则添加到右边
  const item = tempList.value[0];
  // 解决多次快速上拉后,可能数据会乱的问题,因为经过上面的两个await节点查询阻塞一定时间,加上后面的定时器干扰
  // 数组可能变成[],导致此item值可能为undefined
  if (!item) {
    return;
  }
  if (leftRect.height < rightRect.height) {
    leftList.value.push(item);
  } else if (leftRect.height > rightRect.height) {
    rightList.value.push(item);
  } else {
    // 这里是为了保证第一和第二张添加时,左右都能有内容
    // 因为添加第一张,实际队列的高度可能还是0,这时需要根据队列元素长度判断下一个该放哪边
    if (leftList.value.length <= rightList.value.length) {
      leftList.value.push(item);
    } else {
      rightList.value.push(item);
    }
  }
  // 移除临时列表的第一项
  tempList.value.splice(0, 1);
  // 如果临时数组还有数据,继续循环
  if (tempList.value.length) {
    setTimeout(() => {
      splitData();
    }, props.addTime);
  }
};
watch(
  () => props.flowList,
  (nVal, oVal) => {
    if (!oVal) {
      oVal = [];
    }
    if (nVal.length <= oVal.length) {
      leftList.value = [];
      rightList.value = [];
    }
    const length = leftList.value.length + rightList.value.length;
    const diff = nVal.slice(length);
    //差值
    tempList.value = tempList.value.concat(JSON.parse(JSON.stringify(diff)));
    splitData();
  },
  {
    immediate: true,
  }
);
</script>

<style lang="scss" scoped>
.u-waterfall {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
}

.u-column {
  display: flex;
  flex: 1;
  flex-direction: column;
  height: auto;
}

.u-image {
  width: 100%;
}
</style>

相关文章:

  • 【MySQL】用户账户、角色、口令、PAM
  • 【miniconda】centos7安装miniconda
  • 【装饰器】【python】【@wraps详解】装饰器核心问题:元数据丢失解决,以及原理
  • 贪心算法经典应用:最优答疑调度策略详解与Python实现
  • ngx_rtmp_flv_module.c — FLV文件处理模块设计与分析
  • JavaScript基础-常用的键盘事件
  • 第三课:Stable Diffusion图生图入门及应用
  • 跨语言微服务架构(Java、Python)——“API中台”
  • SQL小菜之TOP N查找问题
  • 【SUNO】【AI作词】【提示词】
  • 徘徊检测:视觉分析技术的安防新方向
  • ROS2 humble .launch.py启动文件编写
  • QML输入控件: Dial(1)
  • OLED 播放 GIF图片 Adruino
  • QT高效文件I/O编程--实用指南与最佳实践
  • 基于Spring Boot的网上购物商城系统的设计与实现(LW+源码+讲解)
  • c++:封装红黑树实现map与set
  • NVM安装速通使用手册(Windows版)NVM管理node版本命令手册 NVM使用手册
  • openmmlab介绍 一下
  • 大模型在原发性肺脓肿预测及治疗方案制定中的应用研究
  • 张广智︱“编年事辑”:打开学人心路历程的窗户
  • 美国与卡塔尔签署超2435亿美元经济及军事合作协议
  • 西北大学副校长范代娣成陕西首富?系家庭财富,本人已从上市公司退出
  • 科学家用AI寻找外星生命
  • 山西忻州市人大常委会副主任郭建平接受审查调查
  • 第19届威尼斯建筑双年展开幕,中国案例呈现“容·智慧”