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

背景

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

技术

  • 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;
}

总结

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

相关推荐
gnip4 小时前
企业级配置式表单组件封装
前端·javascript·vue.js
一只叫煤球的猫5 小时前
写代码很6,面试秒变菜鸟?不卖课,面试官视角走心探讨
前端·后端·面试
excel6 小时前
Three.js 材质(Material)详解 —— 区别、原理、场景与示例
前端
掘金安东尼6 小时前
抛弃自定义模态框:原生Dialog的实力
前端·javascript·github
hj5914_前端新手10 小时前
javascript基础- 函数中 this 指向、call、apply、bind
前端·javascript
薛定谔的算法10 小时前
低代码编辑器项目设计与实现:以JSON为核心的数据驱动架构
前端·react.js·前端框架
Hilaku10 小时前
都2025年了,我们还有必要为了兼容性,去写那么多polyfill吗?
前端·javascript·css
yangcode10 小时前
iOS 苹果内购 Storekit 2
前端
LuckySusu10 小时前
【js篇】JavaScript 原型修改 vs 重写:深入理解 constructor的指向问题
前端·javascript
LuckySusu10 小时前
【js篇】如何准确获取对象自身的属性?hasOwnProperty深度解析
前端·javascript