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

背景

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

技术

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

总结

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

相关推荐
开发者小天31 分钟前
为什么 /deep/ 现在不推荐使用?
前端·javascript·node.js
如白驹过隙1 小时前
cloudflare缓存配置
前端·缓存
excel1 小时前
JavaScript 异步编程全解析:Promise、Async/Await 与进阶技巧
前端
Jerry说前后端1 小时前
Android 组件封装实践:从解耦到架构演进
android·前端·架构
步行cgn2 小时前
在 HTML 表单中,name 和 value 属性在 GET 和 POST 请求中的对应关系如下:
前端·hive·html
hrrrrb2 小时前
【Java Web 快速入门】十一、Spring Boot 原理
java·前端·spring boot
一枚小小程序员哈2 小时前
基于Vue的个人博客网站的设计与实现/基于node.js的博客系统的设计与实现#express框架、vscode
vue.js·node.js·express
找不到工作的菜鸟2 小时前
Three.js三大组件:场景(Scene)、相机(Camera)、渲染器(Renderer)
前端·javascript·html
定栓2 小时前
vue3入门-v-model、ref和reactive讲解
前端·javascript·vue.js
专注API从业者2 小时前
基于 Flink 的淘宝实时数据管道设计:商品详情流式处理与异构存储
大数据·前端·数据库·数据挖掘·flink