这么简单的瀑布流,你确定不看

背景

在工作中我们或多或少都遇到过需要用到瀑布流的列表或者需求,那么我们怎么实现瀑布流呢?今天我就给大家带来一个简单的实现方法。给大家做打个样。

技术

  • vue3
  • vite

源码地址

瀑布流地址

后面有时间会将此源码封装成公共组件库-->供大家下载使用--如果大家感兴趣的话可以关注一下

HTML

html 复制代码
<template>
  <div>
    <button @click="addCard">增加</button>
    <div class="card">
      <div class="card-list"
      v-waterfall
      v-for="(item,index) in list" :key="index"
      :style="{backgroundColor:item.color,height:item.height}"
      >
        <p class="text"> {{ index }} </p>
      </div>
    </div>

  </div>
</template>

css

这儿注意-->因为在js中我使用的是transform,所以需要使用到定位

css 复制代码
.card {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  width: 700px;
}
.card-list {
  position: absolute;
  width: 200px;
}

js

实现逻辑:

  • 声明一个列表的高度数组,保存每列的高度,然后获取最小高度的位置,方便定位过去
  • 自定义指令:v-waterfall-->通过mounted拿取到dom元素
  • 获取每列的最小高度就是你当前元素需要的top值,然后根据最小高度的索引值*宽度=left值
  • 最后将其赋值给transform即可--
  • 然后将高度在此(tabulationHeights)基础上叠加即可下次计算

基本逻辑也就完成了。简单吧

javascript 复制代码
import { onMounted, ref, nextTick } from "vue";

const list = ref([
  {color:'#76da6e',height:'100px'},
  {color:'#40a988',height:'70px'},
  {color:'#2384c4',height:'120px'},
  {color:'#106ba3',height:'80px'},
  {color:'#0a589e',height:'110px'},
  {color:'#0a4e98',height:'90px'},
  {color:'#09408c',height:'100px'},
  {color:'#083680',height:'130px'},
]);
const tabulationHeights = ref([0,0,0,0]);

const updateLayout = (el) => {
  const columns = getMinTabulationHeight(tabulationHeights.value);
  const top = tabulationHeights.value[columns];
  const left = columns * el.clientWidth;
  el.style.transform = `translate(${left}px,${top}px)`;
  tabulationHeights.value[columns] += el.offsetHeight;
}

const getMinTabulationHeight = (arr) =>{
  let min = Math.min(...arr);
  return arr.indexOf(min) !== -1 ? arr.indexOf(min) : 0;
}

const vWaterfall = {
  mounted: (el) => {
    updateLayout(el);
  },
  updated: (el) => {
    // updateLayout(el);
  }
}

// 增加
const addCard = () => {
  // 随机生成高度
  const height = Math.floor(Math.random() * 50 + 100);
  // 随机生成颜色
  const color = '#'+Math.floor(Math.random()*16777215).toString(16);
  list.value.push({color,height:height+'px'});
}

疑问

有朋友可能会问:我列表与列表之间肯定不会没有间隔才对啊!那么请问这个有怎么处理呢?

其实这个很简单,比如你是要封装一个组件的话,你只需要传递一个GAP的值:然后拿到这个间距去参与计算即可:如以下代码

javascript 复制代码
const updateLayout = (el) => {
  const columns = getMinTabulationHeight(tabulationHeights.value);
  const top = tabulationHeights.value[columns] + 20;
  const left = (columns * el.clientWidth) + (columns * 20);
  el.style.transform = `translate(${left}px,${top}px)`;
  tabulationHeights.value[columns] += el.offsetHeight + 20;
}

总结

以上只是一个简单的模板,大家可以在此基础上优化优化以便达到自己需要的要求。今天的分享到这里就结束了哦!下次有好的点在来跟大家分享,如果觉得不错可以收藏哈这个源码库,后续会更新插件库

相关推荐
customer0815 分钟前
【开源免费】基于SpringBoot+Vue.JS个人博客系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
乐多_L31 分钟前
使用vue3框架vue-next-admin导出表格excel(带图片)
前端·javascript·vue.js
初尘屿风42 分钟前
基于微信小程序的电影院订票选座系统的设计与实现,SSM+Vue+毕业论文+开题报告+任务书+指导搭建视频
vue.js·微信小程序·小程序
南望无一1 小时前
React Native 0.70.x如何从本地安卓源码(ReactAndroid)构建
前端·react native
Mike_188702783511 小时前
1688代采下单API接口使用指南:实现商品采集与自动化下单
前端·python·自动化
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS打卡健康评测系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
鲨鱼辣椒️面1 小时前
HTML视口动画
前端·html
一小路一1 小时前
Go Web 开发基础:从入门到实战
服务器·前端·后端·面试·golang
堇舟1 小时前
HTML第一节
前端·html
纯粹要努力1 小时前
前端跨域问题及解决方案
前端·javascript·面试